From 5e39ba7076e9212555d206ecae123e1e1e1ac9d5 Mon Sep 17 00:00:00 2001 From: Apress Date: Fri, 7 Oct 2016 04:27:16 +0100 Subject: [PATCH] First commit --- 2077.pdf | Bin 0 -> 206208 bytes 2444.html | 1 + 9781590592397.jpg | Bin 0 -> 9650 bytes LICENSE.txt | 27 + README.md | 15 + contributing.md | 14 + practicals/Chapter03/packages.lisp | 3 + practicals/Chapter03/simple-database.asd | 16 + practicals/Chapter03/simple-database.lisp | 73 + practicals/Chapter08/macro-utilities.asd | 17 + practicals/Chapter08/macro-utilities.lisp | 28 + practicals/Chapter08/packages.lisp | 11 + practicals/Chapter09/packages.lisp | 5 + practicals/Chapter09/test-framework.asd | 15 + practicals/Chapter09/test.lisp | 27 + practicals/Chapter15/packages.lisp | 14 + practicals/Chapter15/pathnames.asd | 17 + practicals/Chapter15/pathnames.lisp | 194 + practicals/Chapter23/packages.lisp | 9 + practicals/Chapter23/spam.asd | 17 + practicals/Chapter23/spam.lisp | 260 + practicals/Chapter24/binary-data.asd | 17 + practicals/Chapter24/binary-data.lisp | 160 + practicals/Chapter24/packages.lisp | 13 + practicals/Chapter25/id3v2.asd | 15 + practicals/Chapter25/id3v2.lisp | 511 + practicals/Chapter25/packages.lisp | 21 + practicals/Chapter26/allegroserve.lisp | 124 + practicals/Chapter26/html-infrastructure.lisp | 81 + practicals/Chapter26/packages.lisp | 10 + practicals/Chapter26/url-function.asd | 19 + practicals/Chapter27/database.lisp | 282 + practicals/Chapter27/mp3-database.asd | 18 + practicals/Chapter27/mp3-database.lisp | 46 + practicals/Chapter27/packages.lisp | 33 + practicals/Chapter28/packages.lisp | 16 + practicals/Chapter28/shoutcast.asd | 20 + practicals/Chapter28/shoutcast.lisp | 129 + practicals/Chapter28/song-source.lisp | 55 + practicals/Chapter29/mp3-browser.asd | 24 + practicals/Chapter29/mp3-browser.css | 14 + practicals/Chapter29/mp3-browser.lisp | 278 + practicals/Chapter29/packages.lisp | 19 + practicals/Chapter29/playlist.lisp | 209 + practicals/Chapter31/README.txt | 8 + practicals/Chapter31/css.lisp | 74 + ...mbed-foo-with-conditions-and-restarts.lisp | 54 + practicals/Chapter31/html.asd | 17 + practicals/Chapter31/html.lisp | 492 + practicals/Chapter31/packages.lisp | 14 + practicals/Chapter32/profiler.lisp | 37 + practicals/LICENSE | 29 + practicals/README.txt | 46 + practicals/libraries/cl-ppcre-1.2.3/CHANGELOG | 236 + practicals/libraries/cl-ppcre-1.2.3/README | 59 + practicals/libraries/cl-ppcre-1.2.3/api.lisp | 1330 ++ .../cl-ppcre-1.2.3/cl-ppcre-test.asd | 40 + .../cl-ppcre-1.2.3/cl-ppcre-test.system | 40 + .../libraries/cl-ppcre-1.2.3/cl-ppcre.asd | 60 + .../libraries/cl-ppcre-1.2.3/cl-ppcre.system | 59 + .../libraries/cl-ppcre-1.2.3/closures.lisp | 583 + .../libraries/cl-ppcre-1.2.3/convert.lisp | 788 + .../doc/benchmarks.2002-12-22.txt | 1546 ++ .../libraries/cl-ppcre-1.2.3/doc/index.html | 2318 +++ .../libraries/cl-ppcre-1.2.3/errors.lisp | 84 + .../libraries/cl-ppcre-1.2.3/lexer.lisp | 769 + practicals/libraries/cl-ppcre-1.2.3/load.lisp | 67 + .../libraries/cl-ppcre-1.2.3/optimize.lisp | 582 + .../libraries/cl-ppcre-1.2.3/packages.lisp | 104 + .../libraries/cl-ppcre-1.2.3/parser.lisp | 347 + .../libraries/cl-ppcre-1.2.3/perltest.pl | 174 + .../libraries/cl-ppcre-1.2.3/ppcre-tests.lisp | 284 + .../libraries/cl-ppcre-1.2.3/regex-class.lisp | 809 + .../cl-ppcre-1.2.3/repetition-closures.lisp | 868 + .../libraries/cl-ppcre-1.2.3/scanner.lisp | 526 + .../libraries/cl-ppcre-1.2.3/specials.lisp | 126 + practicals/libraries/cl-ppcre-1.2.3/testdata | 14288 ++++++++++++++++ practicals/libraries/cl-ppcre-1.2.3/testinput | 3948 +++++ practicals/libraries/cl-ppcre-1.2.3/util.lisp | 313 + practicals/practicals.asd | 27 + 80 files changed, 34023 insertions(+) create mode 100644 2077.pdf create mode 100644 2444.html create mode 100644 9781590592397.jpg create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 contributing.md create mode 100644 practicals/Chapter03/packages.lisp create mode 100644 practicals/Chapter03/simple-database.asd create mode 100644 practicals/Chapter03/simple-database.lisp create mode 100644 practicals/Chapter08/macro-utilities.asd create mode 100644 practicals/Chapter08/macro-utilities.lisp create mode 100644 practicals/Chapter08/packages.lisp create mode 100644 practicals/Chapter09/packages.lisp create mode 100644 practicals/Chapter09/test-framework.asd create mode 100644 practicals/Chapter09/test.lisp create mode 100644 practicals/Chapter15/packages.lisp create mode 100644 practicals/Chapter15/pathnames.asd create mode 100644 practicals/Chapter15/pathnames.lisp create mode 100644 practicals/Chapter23/packages.lisp create mode 100644 practicals/Chapter23/spam.asd create mode 100644 practicals/Chapter23/spam.lisp create mode 100644 practicals/Chapter24/binary-data.asd create mode 100644 practicals/Chapter24/binary-data.lisp create mode 100644 practicals/Chapter24/packages.lisp create mode 100644 practicals/Chapter25/id3v2.asd create mode 100644 practicals/Chapter25/id3v2.lisp create mode 100644 practicals/Chapter25/packages.lisp create mode 100644 practicals/Chapter26/allegroserve.lisp create mode 100644 practicals/Chapter26/html-infrastructure.lisp create mode 100644 practicals/Chapter26/packages.lisp create mode 100644 practicals/Chapter26/url-function.asd create mode 100644 practicals/Chapter27/database.lisp create mode 100644 practicals/Chapter27/mp3-database.asd create mode 100644 practicals/Chapter27/mp3-database.lisp create mode 100644 practicals/Chapter27/packages.lisp create mode 100644 practicals/Chapter28/packages.lisp create mode 100644 practicals/Chapter28/shoutcast.asd create mode 100644 practicals/Chapter28/shoutcast.lisp create mode 100644 practicals/Chapter28/song-source.lisp create mode 100644 practicals/Chapter29/mp3-browser.asd create mode 100644 practicals/Chapter29/mp3-browser.css create mode 100644 practicals/Chapter29/mp3-browser.lisp create mode 100644 practicals/Chapter29/packages.lisp create mode 100644 practicals/Chapter29/playlist.lisp create mode 100644 practicals/Chapter31/README.txt create mode 100644 practicals/Chapter31/css.lisp create mode 100644 practicals/Chapter31/embed-foo-with-conditions-and-restarts.lisp create mode 100644 practicals/Chapter31/html.asd create mode 100644 practicals/Chapter31/html.lisp create mode 100644 practicals/Chapter31/packages.lisp create mode 100644 practicals/Chapter32/profiler.lisp create mode 100644 practicals/LICENSE create mode 100644 practicals/README.txt create mode 100644 practicals/libraries/cl-ppcre-1.2.3/CHANGELOG create mode 100644 practicals/libraries/cl-ppcre-1.2.3/README create mode 100644 practicals/libraries/cl-ppcre-1.2.3/api.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/cl-ppcre-test.asd create mode 100644 practicals/libraries/cl-ppcre-1.2.3/cl-ppcre-test.system create mode 100644 practicals/libraries/cl-ppcre-1.2.3/cl-ppcre.asd create mode 100644 practicals/libraries/cl-ppcre-1.2.3/cl-ppcre.system create mode 100644 practicals/libraries/cl-ppcre-1.2.3/closures.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/convert.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/doc/benchmarks.2002-12-22.txt create mode 100644 practicals/libraries/cl-ppcre-1.2.3/doc/index.html create mode 100644 practicals/libraries/cl-ppcre-1.2.3/errors.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/lexer.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/load.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/optimize.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/packages.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/parser.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/perltest.pl create mode 100644 practicals/libraries/cl-ppcre-1.2.3/ppcre-tests.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/regex-class.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/repetition-closures.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/scanner.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/specials.lisp create mode 100644 practicals/libraries/cl-ppcre-1.2.3/testdata create mode 100644 practicals/libraries/cl-ppcre-1.2.3/testinput create mode 100644 practicals/libraries/cl-ppcre-1.2.3/util.lisp create mode 100644 practicals/practicals.asd diff --git a/2077.pdf b/2077.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0c64cebaa301b3fef70a2145ba43711f69361391 GIT binary patch literal 206208 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
9pENXdLeX?HUA1|U4r93_i04l;w^my5UO#) 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 Fe*h Errata for 582-3 Asleson (corrected in the second printing)

Errata 239-5 Seibel (corrected in the 2nd printing)

Page

Original Sentence

Corrected Sentence

 2

For most languages, however, they payoff isnÕt so easily categorized; it has to do with subjective criteria such as how it feels to use the language.

 

For most languages, however, the payoff isnÕt so easily categorized; it has to do with subjective criteria such as how it feels to use the language.

 

4

If youÕre coming from C++ and Java (or from statically typed functional languages such as Haskel and ML) and refuse to consider living without static type checks, you might as well put this book down now.

 

If youÕre coming from C++ and Java (or from statically typed functional languages such as Haskell and ML) and refuse to consider living without static type checks, you might as well put this book down now.

 

11

Since the Lisp in a Box packaging is designed to get new Lispers up and running in a first-rate Lisp development environment with minimum hassle, all you need to do to get it running is to grab the appropriate package for your operating system and the preferred Lisp from the Lisp in

a Box Web site listed in Chapter 32 and then follow the installation instructions.

 

Since the Lisp in a Box packaging is designed to get new Lispers up and running in a first-rate Lisp development environment with minimum hassle, all you need to do to get it running is to grab the appropriate package for your operating system and the preferred Lisp from the Lisp in

a Box Web site listed in Chapter 32 and then follow the installation instructions.

 

26

CL-USER> (save-db "~/my-cds.db")

CL-USER> (save-db "/home/peter/my-cds.db")

36

If you pass MACROEXPAND-1, a form representing a macro call, it will call the macro code with appropriate arguments and return the expansion.

If you pass MACROEXPAND-1 a form representing a macro call, it will call the macro code with appropriate arguments and return the expansion.

41

10. One other rarely used kind of Lisp form is a list whose first element is a lambda form. IÕll discuss this kind of form in Chapter 5.

10. One other rarely used kind of Lisp form is a list whose first element is a lambda expression. IÕll discuss this kind of form in Chapter 5.

83

Control constructs are the other main kind of looping constructs. Common LispÕs looping facilities are—in addition to being quite powerful and flexible—an interesting lesson in the have-your-cake-and-eat-it-too style of programming that macros provide.

 

Looping constructs are the other main kind of control constructs. Common LispÕs looping facilities are—in addition to being quite powerful and flexible—an interesting lesson in the have-your-cake-and-eat-it-too style of programming that macros provide.

 

87

(format t "Waiting ...~%")

(sleep 1))

(format t "Waiting~%")

(sleep 60))

93

But if you look at the expansion, the list as a whole doesnÕt appear in the expansion; the three element are split up and put in different places.

But if you look at the expansion, the list as a whole doesnÕt appear in the expansion; the three elements are split up and put in different places.

 

122

 

The read syntax for characters objects is simple: #\ followed by the desired character. Thus, #\x is the character x.

 

The read syntax for characters is simple: #\ followed by the desired character. Thus, #\x is the character x.

186

(error "list-directory not implemented"))

(error "file-exists-p not implemented"))

187

 

The :test argument, if provided, specifies another function thatÕs invoked on each pathname before the main function is; the main function will be called only if the test

function returns true.

The :test argument, if provided, specifies another function thatÕs invoked oneach pathname before the main function is; the main function will be called only if the test

function returns true. The default value for the :test argument is a function that always returns true, created by calling the standard function CONSTANTLY.

 

320

 

8. Unfortunately, the language itself doesnÕt falways provide a good model in this respect:

Unfortunately, the language itself doesnÕt always provide a good model in this respect:

322

This way, at the end of the LET, after CALL-NEXT-METHOD returns, the old value of *in-progress-objects* will be restored, effectively popping the object of the stack.

 

This way, at the end of the LET, after CALL-NEXT-METHOD returns, the old value of *in-progress-objects* will be restored, effectively popping the object of the stack.

 

340

 

Putting all these variations together, the ID3 format uses four ways to read and write strings—two characters crossed with two ways of delimiting the string data.

 

Putting all these variations together, the ID3 format uses four ways to read and write strings—two characters crossed with two ways of delimiting the string data.

 

344

(with-open-file (in file)

 

(with-open-file (in file :element-type '(unsigned-byte 8))

 

356

To make matters worse, the number of bytes used to encode description is dependent on the encoding.

To make matters worse, the number of

bytes used to encode text is dependent on the encoding.

356

(defun encoded-string-length (string encoding terminated)

(let ((characters (+ (length string) (if terminated 1 0))))

(* characters (ecase encoding (0 1) (1 2)))))

 

(defun encoded-string-length (string encoding terminated)

(defun encoded-string-length (string encoding terminated)

(let ((characters (+ (length string)

(if terminated 1 0)

(ecase (encoding (0 0) (1 1))))))

(* characters (ecase encoding (0 1) (1 2)))))

361

"Psychedelic" "Rave" "Showtunes" "Trailer" "Lo-Fi" "Tribal"

 

"Psychadelic" "Rave" "Showtunes" "Trailer" "Lo-Fi" "Tribal"

 

361

 

"Slow Rock" "Big Band" "Chorus" "Easy Listening" "Acoustic" "Humor"

 

 

"Slow Rock" "Big Band" "Chorus" "Easy Listening" "Acoustic" "Humour"

 

375

(:input ::type "reset" :value "Reset"))))))))))

 

(:input :type "reset" :value "Reset"))))))))))

 

389

2. As always, the first causality of concise exposition in programming books is proper error handling; in production code youÕd probably want to define your own error type, such as the following, and signal it instead:

 

2. As always, the first casualty of concise exposition in programming books is proper error handling; in production code youÕd probably want to define your own error type, such as the following, and signal it instead:

 

418

The call to update-current-if-necessary will take care of setting current-song to NIL.

The call to update-current-if-necessary will take care of setting current-song to emptyplaylist- song.

 

 

432

 

Obviously, if you generate HTML by just printing strings to a stream, then itÕs up to you to replace any occurrences of

those characters in the string with the appropriate escape sequences, &lt, &gt and &amp;.

 

Obviously, if you generate HTML by just printing strings to a stream, then itÕs up to you to replace any occurrences of

those characters in the string with the appropriate escape sequences, &lt; &gt; and &amp;.

 

432

 

2. Well, almost every tag. Certain tags such as IMG and BR donÕt. YouÕll deal with those in the section ÒThe Basic Evaluation Rule.Ó

 

 

2. Well, almost every tag. Certain tags such as IMG and BR arenÕt. YouÕll deal with those in the section ÒThe Basic Evaluation Rule.Ó

 

 

\ No newline at end of file diff --git a/9781590592397.jpg b/9781590592397.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3d7c7057cac50125b2080ece65f850c8a070bb8c GIT binary patch literal 9650 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 a)Wc0HzFdY*hB" + :version "1.0" + :maintainer "Peter Seibel " + :licence "BSD" + :description "Simple s-expression database." + :long-description "" + :components + ((:file "packages") + (:file "simple-database" :depends-on ("packages")))) + + diff --git a/practicals/Chapter03/simple-database.lisp b/practicals/Chapter03/simple-database.lisp new file mode 100644 index 0000000..afaf92b --- /dev/null +++ b/practicals/Chapter03/simple-database.lisp @@ -0,0 +1,73 @@ +(in-package :com.gigamonkeys.simple-db) + +(defvar *db* nil) + +(defun make-cd (title artist rating ripped) + (list :title title :artist artist :rating rating :ripped ripped)) + +(defun add-record (cd) (push cd *db*)) + +(defun dump-db () + (dolist (cd *db*) + (format t "~{~a:~10t~a~%~}~%" cd))) + +(defun prompt-read (prompt) + (format *query-io* "~a: " prompt) + (force-output *query-io*) + (read-line *query-io*)) + +(defun prompt-for-cd () + (make-cd + (prompt-read "Title") + (prompt-read "Artist") + (or (parse-integer (prompt-read "Rating") :junk-allowed t) 0) + (y-or-n-p "Ripped [y/n]: "))) + +(defun add-cds () + (loop (add-record (prompt-for-cd)) + (if (not (y-or-n-p "Another? [y/n]: ")) (return)))) + +(defun save-db (filename) + (with-open-file (out filename + :direction :output + :if-exists :supersede) + (with-standard-io-syntax + (print *db* out)))) + +(defun load-db (filename) + (with-open-file (in filename) + (with-standard-io-syntax + (setf *db* (read in))))) + +(defun clear-db () (setq *db* nil)) + +(defun select (selector-fn) + (remove-if-not selector-fn *db*)) + +(defmacro where (&rest clauses) + `#'(lambda (cd) (and ,@(make-comparisons-list clauses)))) + +(defun make-comparisons-list (fields) + (loop while fields + collecting (make-comparison-expr (pop fields) (pop fields)))) + +(defun make-comparison-expr (field value) + `(equal (getf cd ,field) ,value)) + + +(defun update (selector-fn &key title artist rating (ripped nil ripped-p)) + (setf *db* + (mapcar + #'(lambda (row) + (when (funcall selector-fn row) + (if title (setf (getf row :title) title)) + (if artist (setf (getf row :artist) artist)) + (if rating (setf (getf row :rating) rating)) + (if ripped-p (setf (getf row :ripped) ripped))) + row) *db*))) + +(defun delete-rows (selector-fn) + (setf *db* (remove-if selector-fn *db*))) + + + diff --git a/practicals/Chapter08/macro-utilities.asd b/practicals/Chapter08/macro-utilities.asd new file mode 100644 index 0000000..bda1aab --- /dev/null +++ b/practicals/Chapter08/macro-utilities.asd @@ -0,0 +1,17 @@ +(defpackage :com.gigamonkeys.macro-utilities-system (:use :asdf :cl)) +(in-package :com.gigamonkeys.macro-utilities-system) + +(defsystem macro-utilities + :name "macro-utilities" + :author "Peter Seibel " + :version "1.0" + :maintainer "Peter Seibel " + :licence "BSD" + :description "Utilities for writing macros" + :long-description "" + :components + ((:file "packages") + (:file "macro-utilities" :depends-on ("packages"))) + :depends-on ()) + + diff --git a/practicals/Chapter08/macro-utilities.lisp b/practicals/Chapter08/macro-utilities.lisp new file mode 100644 index 0000000..1ddeade --- /dev/null +++ b/practicals/Chapter08/macro-utilities.lisp @@ -0,0 +1,28 @@ +(in-package :com.gigamonkeys.macro-utilities) + +(defmacro with-gensyms ((&rest names) &body body) + `(let ,(loop for n in names collect `(,n (make-symbol ,(string n)))) + ,@body)) + +(defmacro once-only ((&rest names) &body body) + (let ((gensyms (loop for n in names collect (gensym (string n))))) + `(let (,@(loop for g in gensyms collect `(,g (gensym)))) + `(let (,,@(loop for g in gensyms for n in names collect ``(,,g ,,n))) + ,(let (,@(loop for n in names for g in gensyms collect `(,n ,g))) + ,@body))))) + +(defun spliceable (value) + (if value (list value))) + +(defmacro ppme (form &environment env) + (progn + (write (macroexpand-1 form env) + :length nil + :level nil + :circle nil + :pretty t + :gensym nil + :right-margin 83 + :case :downcase) + nil)) + diff --git a/practicals/Chapter08/packages.lisp b/practicals/Chapter08/packages.lisp new file mode 100644 index 0000000..7827127 --- /dev/null +++ b/practicals/Chapter08/packages.lisp @@ -0,0 +1,11 @@ +(in-package :cl-user) + +(defpackage :com.gigamonkeys.macro-utilities + (:use :common-lisp) + (:export + :with-gensyms + :with-gensymed-defuns + :once-only + :spliceable + :ppme)) + diff --git a/practicals/Chapter09/packages.lisp b/practicals/Chapter09/packages.lisp new file mode 100644 index 0000000..bede025 --- /dev/null +++ b/practicals/Chapter09/packages.lisp @@ -0,0 +1,5 @@ +(in-package :cl-user) + +(defpackage :com.gigamonkeys.test + (:use :common-lisp :com.gigamonkeys.macro-utilities) + (:export :deftest :check)) diff --git a/practicals/Chapter09/test-framework.asd b/practicals/Chapter09/test-framework.asd new file mode 100644 index 0000000..471cd5b --- /dev/null +++ b/practicals/Chapter09/test-framework.asd @@ -0,0 +1,15 @@ +(defpackage :com.gigamonkeys.test-system (:use :asdf :cl)) +(in-package :com.gigamonkeys.test-system) + +(defsystem test-framework + :name "test-framework" + :author "Peter Seibel " + :version "1.0" + :maintainer "Peter Seibel " + :licence "BSD" + :description "Simple unit test framework for Common Lisp" + :long-description "" + :components + ((:file "packages") + (:file "test" :depends-on ("packages"))) + :depends-on (:macro-utilities)) diff --git a/practicals/Chapter09/test.lisp b/practicals/Chapter09/test.lisp new file mode 100644 index 0000000..c52af99 --- /dev/null +++ b/practicals/Chapter09/test.lisp @@ -0,0 +1,27 @@ +(in-package :com.gigamonkeys.test) + +(defvar *test-name* nil) + +(defmacro deftest (name parameters &body body) + "Define a test function. Within a test function we can call other +test functions or use `check' to run individual test cases." + `(defun ,name ,parameters + (let ((*test-name* (append *test-name* (list ',name)))) + ,@body))) + +(defmacro check (&body forms) + "Run each expression in `forms' as a test case." + `(combine-results + ,@(loop for f in forms collect `(report-result ,f ',f)))) + +(defmacro combine-results (&body forms) + "Combine the results (as booleans) of evaluating `forms' in order." + (with-gensyms (result) + `(let ((,result t)) + ,@(loop for f in forms collect `(unless ,f (setf ,result nil))) + ,result))) + +(defun report-result (result form) + "Report the results of a single test case. Called by `check'." + (format t "~:[FAIL~;pass~] ... ~a: ~a~%" result *test-name* form) + result) diff --git a/practicals/Chapter15/packages.lisp b/practicals/Chapter15/packages.lisp new file mode 100644 index 0000000..84251cc --- /dev/null +++ b/practicals/Chapter15/packages.lisp @@ -0,0 +1,14 @@ +(in-package :cl-user) + +(defpackage :com.gigamonkeys.pathnames + (:use :common-lisp) + (:export + :list-directory + :file-exists-p + :directory-pathname-p + :file-pathname-p + :pathname-as-directory + :pathname-as-file + :walk-directory + :directory-p + :file-p)) diff --git a/practicals/Chapter15/pathnames.asd b/practicals/Chapter15/pathnames.asd new file mode 100644 index 0000000..302be83 --- /dev/null +++ b/practicals/Chapter15/pathnames.asd @@ -0,0 +1,17 @@ +(defpackage :com.gigamonkeys.pathnames-system (:use :asdf :cl)) +(in-package :com.gigamonkeys.pathnames-system) + +(defsystem pathnames + :name "pathnames" + :author "Peter Seibel " + :version "1.0" + :maintainer "Peter Seibel " + :licence "BSD" + :description "Portable pathname manipulation functions." + :long-description "" + :components + ((:file "packages") + (:file "pathnames" :depends-on ("packages")))) + + + diff --git a/practicals/Chapter15/pathnames.lisp b/practicals/Chapter15/pathnames.lisp new file mode 100644 index 0000000..fb92b14 --- /dev/null +++ b/practicals/Chapter15/pathnames.lisp @@ -0,0 +1,194 @@ +(in-package #:com.gigamonkeys.pathnames) + +(defun list-directory (dirname) + "Return a list of the contents of the directory named by dirname. +Names of subdirectories will be returned in `directory normal +form'. Unlike CL:DIRECTORY, LIST-DIRECTORY does not accept +wildcard pathnames; `dirname' should simply be a pathname that +names a directory. It can be in either file or directory form." + (when (wild-pathname-p dirname) + (error "Can only list concrete directory names.")) + + (let ((wildcard (directory-wildcard dirname))) + + #+(or sbcl cmu lispworks) + ;; SBCL, CMUCL, and Lispworks return subdirectories in directory + ;; form just the way we want. + (directory wildcard) + + #+openmcl + ;; OpenMCl by default doesn't return subdirectories at all. But + ;; when prodded to do so with the special argument :directories, + ;; it returns them in directory form. + (directory wildcard :directories t) + + #+allegro + ;; Allegro normally return directories in file form but we can + ;; change that with the :directories-are-files argument. + (directory wildcard :directories-are-files nil) + + #+clisp + ;; CLISP has a particularly idiosyncratic view of things. But we + ;; can bludgeon even it into doing what we want. + (nconc + ;; CLISP won't list files without an extension when :type is + ;; wild so we make a special wildcard for it. + (directory wildcard) + ;; And CLISP doesn't consider subdirectories to match unless + ;; there is a :wild in the directory component. + (directory (clisp-subdirectories-wildcard wildcard))) + + #-(or sbcl cmu lispworks openmcl allegro clisp) + (error "list-directory not implemented"))) + + + + +(defun file-exists-p (pathname) + "Similar to CL:PROBE-FILE except it always returns directory names +in `directory normal form'. Returns truename which will be in +`directory form' if file named is, in fact, a directory." + + #+(or sbcl lispworks openmcl) + ;; These implementations do "The Right Thing" as far as we are + ;; concerned. They return a truename of the file or directory if it + ;; exists and the truename of a directory is in directory normal + ;; form. + (probe-file pathname) + + #+(or allegro cmu) + ;; These implementations accept the name of a directory in either + ;; form and return the name in the form given. However the name of a + ;; file must be given in file form. So we try first with a directory + ;; name which will return NIL if either the file doesn't exist at + ;; all or exists and is not a directory. Then we try with a file + ;; form name. + (or (probe-file (pathname-as-directory pathname)) + (probe-file pathname)) + + #+clisp + ;; Once again CLISP takes a particularly unforgiving approach, + ;; signalling ERRORs at the slightest provocation. + + ;; pathname in file form and actually a file -- (probe-file file) ==> truename + ;; pathname in file form and doesn't exist -- (probe-file file) ==> NIL + ;; pathname in dir form and actually a directory -- (probe-directory file) ==> truename + ;; pathname in dir form and doesn't exist -- (probe-directory file) ==> NIL + + ;; pathname in file form and actually a directory -- (probe-file file) ==> ERROR + ;; pathname in dir form and actually a file -- (probe-directory file) ==> ERROR + (or (ignore-errors + ;; PROBE-FILE will return the truename if file exists and is a + ;; file or NIL if it doesn't exist at all. If it exists but is + ;; a directory PROBE-FILE will signal an error which we + ;; ignore. + (probe-file (pathname-as-file pathname))) + (ignore-errors + ;; PROBE-DIRECTORY returns T if the file exists and is a + ;; directory or NIL if it doesn't exist at all. If it exists + ;; but is a file, PROBE-DIRECTORY will signal an error. + (let ((directory-form (pathname-as-directory pathname))) + (when (ext:probe-directory directory-form) + directory-form)))) + + + #-(or sbcl cmu lispworks openmcl allegro clisp) + (error "list-directory not implemented")) + +(defun directory-wildcard (dirname) + (make-pathname + :name :wild + :type #-clisp :wild #+clisp nil + :defaults (pathname-as-directory dirname))) + +#+clisp +(defun clisp-subdirectories-wildcard (wildcard) + (make-pathname + :directory (append (pathname-directory wildcard) (list :wild)) + :name nil + :type nil + :defaults wildcard)) + + +(defun directory-pathname-p (p) + "Is the given pathname the name of a directory? This function can +usefully be used to test whether a name returned by LIST-DIRECTORIES +or passed to the function in WALK-DIRECTORY is the name of a directory +in the file system since they always return names in `directory normal +form'." + (flet ((component-present-p (value) + (and value (not (eql value :unspecific))))) + (and + (not (component-present-p (pathname-name p))) + (not (component-present-p (pathname-type p))) + p))) + + +(defun file-pathname-p (p) + (unless (directory-pathname-p p) p)) + +(defun pathname-as-directory (name) + "Return a pathname reperesenting the given pathname in +`directory normal form', i.e. with all the name elements in the +directory component and NIL in the name and type components. Can +not be used on wild pathnames because there's not portable way to +convert wildcards in the name and type into a single directory +component. Returns its argument if name and type are both nil or +:unspecific." + (let ((pathname (pathname name))) + (when (wild-pathname-p pathname) + (error "Can't reliably convert wild pathnames.")) + (if (not (directory-pathname-p name)) + (make-pathname + :directory (append (or (pathname-directory pathname) (list :relative)) + (list (file-namestring pathname))) + :name nil + :type nil + :defaults pathname) + pathname))) + +(defun pathname-as-file (name) + "Return a pathname reperesenting the given pathname in `file form', +i.e. with the name elements in the name and type component. Can't +convert wild pathnames because of problems mapping wild directory +component into name and type components. Returns its argument if +it is already in file form." + (let ((pathname (pathname name))) + (when (wild-pathname-p pathname) + (error "Can't reliably convert wild pathnames.")) + (if (directory-pathname-p name) + (let* ((directory (pathname-directory pathname)) + (name-and-type (pathname (first (last directory))))) + (make-pathname + :directory (butlast directory) + :name (pathname-name name-and-type) + :type (pathname-type name-and-type) + :defaults pathname)) + pathname))) + +(defun walk-directory (dirname fn &key directories (test (constantly t))) + "Walk a directory invoking `fn' on each pathname found. If `test' is +supplied fn is invoked only on pathnames for which `test' returns +true. If `directories' is t invokes `test' and `fn' on directory +pathnames as well." + (labels + ((walk (name) + (cond + ((directory-pathname-p name) + (when (and directories (funcall test name)) + (funcall fn name)) + (dolist (x (list-directory name)) (walk x))) + ((funcall test name) (funcall fn name))))) + (walk (pathname-as-directory dirname)))) + +(defun directory-p (name) + "Is `name' the name of an existing directory." + (let ((truename (file-exists-p name))) + (and truename (directory-pathname-p name)))) + +(defun file-p (name) + "Is `name' the name of an existing file, i.e. not a directory." + (let ((truename (file-exists-p name))) + (and truename (file-pathname-p name)))) + + diff --git a/practicals/Chapter23/packages.lisp b/practicals/Chapter23/packages.lisp new file mode 100644 index 0000000..b542e3d --- /dev/null +++ b/practicals/Chapter23/packages.lisp @@ -0,0 +1,9 @@ +(in-package :cl-user) + +(defpackage :com.gigamonkeys.spam + (:use :common-lisp + :com.gigamonkeys.test + :com.gigamonkeys.pathnames)) + + + diff --git a/practicals/Chapter23/spam.asd b/practicals/Chapter23/spam.asd new file mode 100644 index 0000000..d5f2781 --- /dev/null +++ b/practicals/Chapter23/spam.asd @@ -0,0 +1,17 @@ +(defpackage :com.gigamonkeys.spam-system (:use :asdf :cl)) +(in-package :com.gigamonkeys.spam-system) + +(defsystem spam + :name "spam" + :author "Peter Seibel " + :version "1.0" + :maintainer "Peter Seibel " + :licence "BSD" + :description "Spam filter" + :long-description "" + :components + ((:file "packages") + (:file "spam" :depends-on ("packages"))) + :depends-on (:cl-ppcre :pathnames)) + + diff --git a/practicals/Chapter23/spam.lisp b/practicals/Chapter23/spam.lisp new file mode 100644 index 0000000..310a570 --- /dev/null +++ b/practicals/Chapter23/spam.lisp @@ -0,0 +1,260 @@ +(in-package :com.gigamonkeys.spam) + +(defvar *feature-database* (make-hash-table :test #'equal)) +(defvar *total-spams* 0) +(defvar *total-hams* 0) + +(defparameter *max-ham-score* .4) +(defparameter *min-spam-score* .6) + +(defparameter *max-chars* (* 10 1024)) +(defparameter *corpus* (make-array 1000 :adjustable t :fill-pointer 0)) + +(defun classify (text) + "Classify the text of a message as SPAM, HAM, or UNSURE." + (classification (score (extract-features text)))) + + +(defclass word-feature () + ((word + :initarg :word + :accessor word + :initform (error "Must supply :word") + :documentation "The word this feature represents.") + (spam-count + :initarg :spam-count + :accessor spam-count + :initform 0 + :documentation "Number of spams we have seen this feature in.") + (ham-count + :initarg :ham-count + :accessor ham-count + :initform 0 + :documentation "Number of hams we have seen this feature in."))) + +(defun intern-feature (word) + (or (gethash word *feature-database*) + (setf (gethash word *feature-database*) + (make-instance 'word-feature :word word)))) + +(defun extract-words (text) + (delete-duplicates + (cl-ppcre:all-matches-as-strings "[a-zA-Z]{3,}" text) + :test #'string=)) + +(defun extract-features (text) + (mapcar #'intern-feature (extract-words text))) + +(defmethod print-object ((object word-feature) stream) + (print-unreadable-object (object stream :type t) + (with-slots (word ham-count spam-count) object + (format stream "~s :hams ~d :spams ~d" word ham-count spam-count)))) + +(defun train (text type) + (dolist (feature (extract-features text)) + (increment-count feature type)) + (increment-total-count type)) + +(defun increment-count (feature type) + (ecase type + (ham (incf (ham-count feature))) + (spam (incf (spam-count feature))))) + +(defun increment-total-count (type) + (ecase type + (ham (incf *total-hams*)) + (spam (incf *total-spams*)))) + +(defun clear-database () + (setf + *feature-database* (make-hash-table :test #'equal) + *total-spams* 0 + *total-hams* 0)) + +(defun spam-probability (feature) + "Basic probability that a feature with the given relative +frequencies will appear in a spam assuming spams and hams are +otherwise equally probable. One of the two frequencies must be +non-zero." + (with-slots (spam-count ham-count) feature + (let ((spam-frequency (/ spam-count (max 1 *total-spams*))) + (ham-frequency (/ ham-count (max 1 *total-hams*)))) + (/ spam-frequency (+ spam-frequency ham-frequency))))) + + +(defun bayesian-spam-probability (feature &optional + (assumed-probability 1/2) + (weight 1)) + "Bayesian adjustment of a given probability given the number of +data points that went into it, an assumed probability, and a +weight we give that assumed probability." + (let ((basic-probability (spam-probability feature)) + (data-points (+ (spam-count feature) (ham-count feature)))) + (/ (+ (* weight assumed-probability) + (* data-points basic-probability)) + (+ weight data-points)))) + +(defun score (features) + (let ((spam-probs ()) (ham-probs ()) (number-of-probs 0)) + (dolist (feature features) + (unless (untrained-p feature) + (let ((spam-prob (float (bayesian-spam-probability feature) 0.0d0))) + (push spam-prob spam-probs) + (push (- 1.0d0 spam-prob) ham-probs) + (incf number-of-probs)))) + (let ((h (- 1 (fisher spam-probs number-of-probs))) + (s (- 1 (fisher ham-probs number-of-probs)))) + (/ (+ (- 1 h) s) 2.0d0)))) + +(defun untrained-p (feature) + (with-slots (spam-count ham-count) feature + (and (zerop spam-count) (zerop ham-count)))) + +(defun fisher (probs number-of-probs) + "The Fisher computation described by Robinson." + (inverse-chi-square + (* -2 (reduce #'+ probs :key #'log)) + (* 2 number-of-probs))) + +(defun inverse-chi-square (value degrees-of-freedom) + "Probability that chi-square >= value with given degrees-of-freedom. +Based on Gary Robinson's Python implementation." + (assert (evenp degrees-of-freedom)) + ;; Due to rounding errors in the multiplication and exponentiation + ;; the sum computed in the loop may end up a shade above 1.0 which + ;; we can't have since it's supposed to represent a probability. + (min + (loop with m = (/ value 2) + for i below (/ degrees-of-freedom 2) + for prob = (exp (- m)) then (* prob (/ m i)) + summing prob) + 1.0)) + +(defun classification (score) + (values + (cond + ((<= score *max-ham-score*) 'ham) + ((>= score *min-spam-score*) 'spam) + (t 'unsure)) + score)) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Test rig + +(defun add-file-to-corpus (filename type corpus) + (vector-push-extend (list filename type) corpus)) + +(defun add-directory-to-corpus (dir type corpus) + (dolist (filename (list-directory dir)) + (add-file-to-corpus filename type corpus))) + +(defun test-classifier (corpus testing-fraction) + (clear-database) + (let* ((shuffled (shuffle-vector corpus)) + (size (length corpus)) + (train-on (floor (* size (- 1 testing-fraction))))) + (train-from-corpus shuffled :start 0 :end train-on) + (test-from-corpus shuffled :start train-on))) + +(defun train-from-corpus (corpus &key (start 0) end) + (loop for idx from start below (or end (length corpus)) do + (destructuring-bind (file type) (aref corpus idx) + (train (start-of-file file *max-chars*) type)))) + +(defun test-from-corpus (corpus &key (start 0) end) + (loop for idx from start below (or end (length corpus)) collect + (destructuring-bind (file type) (aref corpus idx) + (multiple-value-bind (classification score) + (classify (start-of-file file *max-chars*)) + (list + :file file + :type type + :classification classification + :score score))))) + +(defun nshuffle-vector (vector) + "Shuffle a vector in place using Fisher-Yates algorithm." + (loop for idx downfrom (1- (length vector)) to 1 + for other = (random (1+ idx)) + do (unless (= idx other) + (rotatef (aref vector idx) (aref vector other)))) + vector) + +(defun shuffle-vector (vector) + "Return a shuffled copy of vector." + (nshuffle-vector (copy-seq vector))) + +(defun start-of-file (file max-chars) + (with-open-file (in file) + (let* ((length (min (file-length in) max-chars)) + (text (make-string length)) + (read (read-sequence text in))) + (if (< read length) + (subseq text 0 read) + text)))) + + +(defun result-type (result) + (destructuring-bind (&key type classification &allow-other-keys) result + (ecase type + (ham + (ecase classification + (ham 'correct) + (spam 'false-positive) + (unsure 'missed-ham))) + (spam + (ecase classification + (ham 'false-negative) + (spam 'correct) + (unsure 'missed-spam)))))) + +(defun false-positive-p (result) + (eql (result-type result) 'false-positive)) + +(defun false-negative-p (result) + (eql (result-type result) 'false-negative)) + +(defun missed-ham-p (result) + (eql (result-type result) 'missed-ham)) + +(defun missed-spam-p (result) + (eql (result-type result) 'missed-spam)) + +(defun correct-p (result) + (eql (result-type result) 'correct)) + +(defun analyze-results (results) + (let* ((keys '(total correct false-positive + false-negative missed-ham missed-spam)) + (counts (loop for x in keys collect (cons x 0)))) + (dolist (item results) + (incf (cdr (assoc 'total counts))) + (incf (cdr (assoc (result-type item) counts)))) + (loop with total = (cdr (assoc 'total counts)) + for (label . count) in counts + do (format t "~&~@(~a~):~20t~5d~,5t: ~6,2f%~%" + label count (* 100 (/ count total)))))) + +(defun explain-classification (file) + (let* ((text (start-of-file file *max-chars*)) + (features (extract-features text)) + (score (score features)) + (classification (classification score))) + (show-summary file text classification score) + (dolist (feature (sorted-interesting features)) + (show-feature feature)))) + +(defun show-summary (file text classification score) + (format t "~&~a" file) + (format t "~2%~a~2%" text) + (format t "Classified as ~a with score of ~,5f~%" classification score)) + +(defun show-feature (feature) + (with-slots (word ham-count spam-count) feature + (format + t "~&~2t~a~30thams: ~5d; spams: ~5d;~,10tprob: ~,f~%" + word ham-count spam-count (bayesian-spam-probability feature)))) + +(defun sorted-interesting (features) + (sort (remove-if #'untrained-p features) #'< :key #'bayesian-spam-probability)) diff --git a/practicals/Chapter24/binary-data.asd b/practicals/Chapter24/binary-data.asd new file mode 100644 index 0000000..b3c399c --- /dev/null +++ b/practicals/Chapter24/binary-data.asd @@ -0,0 +1,17 @@ +(defpackage :com.gigamonkeys.binary-data-system (:use :asdf :cl)) +(in-package :com.gigamonkeys.binary-data-system) + +(defsystem binary-data + :name "binary-data" + :author "Peter Seibel " + :version "1.0" + :maintainer "Peter Seibel " + :licence "BSD" + :description "Parser for binary data files. " + :long-description "" + :components + ((:file "packages") + (:file "binary-data" :depends-on ("packages"))) + :depends-on (:macro-utilities)) + + diff --git a/practicals/Chapter24/binary-data.lisp b/practicals/Chapter24/binary-data.lisp new file mode 100644 index 0000000..80f264b --- /dev/null +++ b/practicals/Chapter24/binary-data.lisp @@ -0,0 +1,160 @@ +(in-package :com.gigamonkeys.binary-data) + +(defvar *in-progress-objects* nil) + +(defconstant +null+ (code-char 0)) + +(defgeneric read-value (type stream &key) + (:documentation "Read a value of the given type from the stream.")) + +(defgeneric write-value (type stream value &key) + (:documentation "Write a value as the given type to the stream.")) + +(defgeneric read-object (object stream) + (:method-combination progn :most-specific-last) + (:documentation "Fill in the slots of object from stream.")) + +(defgeneric write-object (object stream) + (:method-combination progn :most-specific-last) + (:documentation "Write out the slots of object to the stream.")) + +(defmethod read-value ((type symbol) stream &key) + (let ((object (make-instance type))) + (read-object object stream) + object)) + +(defmethod write-value ((type symbol) stream value &key) + (assert (typep value type)) + (write-object value stream)) + + +;;; Binary types + +(defmacro define-binary-type (name (&rest args) &body spec) + (with-gensyms (type stream value) + `(progn + (defmethod read-value ((,type (eql ',name)) ,stream &key ,@args) + (declare (ignorable ,@args)) + ,(type-reader-body spec stream)) + (defmethod write-value ((,type (eql ',name)) ,stream ,value &key ,@args) + (declare (ignorable ,@args)) + ,(type-writer-body spec stream value))))) + +(defun type-reader-body (spec stream) + (ecase (length spec) + (1 (destructuring-bind (type &rest args) (mklist (first spec)) + `(read-value ',type ,stream ,@args))) + (2 (destructuring-bind ((in) &body body) (cdr (assoc :reader spec)) + `(let ((,in ,stream)) ,@body))))) + +(defun type-writer-body (spec stream value) + (ecase (length spec) + (1 (destructuring-bind (type &rest args) (mklist (first spec)) + `(write-value ',type ,stream ,value ,@args))) + (2 (destructuring-bind ((out v) &body body) (cdr (assoc :writer spec)) + `(let ((,out ,stream) (,v ,value)) ,@body))))) + + +;;; Binary classes + +(defmacro define-generic-binary-class (name (&rest superclasses) slots read-method) + (with-gensyms (objectvar streamvar) + `(progn + (eval-when (:compile-toplevel :load-toplevel :execute) + (setf (get ',name 'slots) ',(mapcar #'first slots)) + (setf (get ',name 'superclasses) ',superclasses)) + + (defclass ,name ,superclasses + ,(mapcar #'slot->defclass-slot slots)) + + ,read-method + + (defmethod write-object progn ((,objectvar ,name) ,streamvar) + (declare (ignorable ,streamvar)) + (with-slots ,(new-class-all-slots slots superclasses) ,objectvar + ,@(mapcar #'(lambda (x) (slot->write-value x streamvar)) slots)))))) + +(defmacro define-binary-class (name (&rest superclasses) slots) + (with-gensyms (objectvar streamvar) + `(define-generic-binary-class ,name ,superclasses ,slots + (defmethod read-object progn ((,objectvar ,name) ,streamvar) + (declare (ignorable ,streamvar)) + (with-slots ,(new-class-all-slots slots superclasses) ,objectvar + ,@(mapcar #'(lambda (x) (slot->read-value x streamvar)) slots)))))) + +(defmacro define-tagged-binary-class (name (&rest superclasses) slots &rest options) + (with-gensyms (typevar objectvar streamvar) + `(define-generic-binary-class ,name ,superclasses ,slots + (defmethod read-value ((,typevar (eql ',name)) ,streamvar &key) + (let* ,(mapcar #'(lambda (x) (slot->binding x streamvar)) slots) + (let ((,objectvar + (make-instance + ,@(or (cdr (assoc :dispatch options)) + (error "Must supply :disptach form.")) + ,@(mapcan #'slot->keyword-arg slots)))) + (read-object ,objectvar ,streamvar) + ,objectvar)))))) + +(defun as-keyword (sym) (intern (string sym) :keyword)) + +(defun normalize-slot-spec (spec) + (list (first spec) (mklist (second spec)))) + +(defun mklist (x) (if (listp x) x (list x))) + +(defun slot->defclass-slot (spec) + (let ((name (first spec))) + `(,name :initarg ,(as-keyword name) :accessor ,name))) + +(defun slot->read-value (spec stream) + (destructuring-bind (name (type &rest args)) (normalize-slot-spec spec) + `(setf ,name (read-value ',type ,stream ,@args)))) + +(defun slot->write-value (spec stream) + (destructuring-bind (name (type &rest args)) (normalize-slot-spec spec) + `(write-value ',type ,stream ,name ,@args))) + +(defun slot->binding (spec stream) + (destructuring-bind (name (type &rest args)) (normalize-slot-spec spec) + `(,name (read-value ',type ,stream ,@args)))) + +(defun slot->keyword-arg (spec) + (let ((name (first spec))) + `(,(as-keyword name) ,name))) + +;;; Keeping track of inherited slots + +(defun direct-slots (name) + (copy-list (get name 'slots))) + +(defun inherited-slots (name) + (loop for super in (get name 'superclasses) + nconc (direct-slots super) + nconc (inherited-slots super))) + +(defun all-slots (name) + (nconc (direct-slots name) (inherited-slots name))) + +(defun new-class-all-slots (slots superclasses) + "Like all slots but works while compiling a new class before slots +and superclasses have been saved." + (nconc (mapcan #'all-slots superclasses) (mapcar #'first slots))) + +;;; In progress Object stack + +(defun current-binary-object () + (first *in-progress-objects*)) + +(defun parent-of-type (type) + (find-if #'(lambda (x) (typep x type)) *in-progress-objects*)) + +(defmethod read-object :around (object stream) + (declare (ignore stream)) + (let ((*in-progress-objects* (cons object *in-progress-objects*))) + (call-next-method))) + +(defmethod write-object :around (object stream) + (declare (ignore stream)) + (let ((*in-progress-objects* (cons object *in-progress-objects*))) + (call-next-method))) + diff --git a/practicals/Chapter24/packages.lisp b/practicals/Chapter24/packages.lisp new file mode 100644 index 0000000..c091aef --- /dev/null +++ b/practicals/Chapter24/packages.lisp @@ -0,0 +1,13 @@ +(in-package :cl-user) + +(defpackage :com.gigamonkeys.binary-data + (:use :common-lisp :com.gigamonkeys.macro-utilities) + (:export :define-binary-class + :define-tagged-binary-class + :define-binary-type + :read-value + :write-value + :*in-progress-objects* + :parent-of-type + :current-binary-object + :+null+)) diff --git a/practicals/Chapter25/id3v2.asd b/practicals/Chapter25/id3v2.asd new file mode 100644 index 0000000..e69430c --- /dev/null +++ b/practicals/Chapter25/id3v2.asd @@ -0,0 +1,15 @@ +(defpackage :com.gigamonkeys.id3v2-system (:use :asdf :cl)) +(in-package :com.gigamonkeys.id3v2-system) + +(defsystem id3v2 + :name "id3" + :author "Peter Seibel " + :version "1.0" + :maintainer "Peter Seibel " + :licence "BSD" + :description "ID3v2 parser. " + :long-description "" + :components + ((:file "packages") + (:file "id3v2" :depends-on ("packages"))) + :depends-on (:binary-data :pathnames)) diff --git a/practicals/Chapter25/id3v2.lisp b/practicals/Chapter25/id3v2.lisp new file mode 100644 index 0000000..fdb8dbe --- /dev/null +++ b/practicals/Chapter25/id3v2.lisp @@ -0,0 +1,511 @@ +(in-package #:com.gigamonkeys.id3v2) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; A few basic types + +(define-binary-type unsigned-integer (bytes bits-per-byte) + (:reader (in) + (loop with value = 0 + for low-bit downfrom (* bits-per-byte (1- bytes)) to 0 by bits-per-byte do + (setf (ldb (byte bits-per-byte low-bit) value) (read-byte in)) + finally (return value))) + (:writer (out value) + (loop for low-bit downfrom (* bits-per-byte (1- bytes)) to 0 by bits-per-byte + do (write-byte (ldb (byte bits-per-byte low-bit) value) out)))) + +(define-binary-type u1 () (unsigned-integer :bytes 1 :bits-per-byte 8)) +(define-binary-type u2 () (unsigned-integer :bytes 2 :bits-per-byte 8)) +(define-binary-type u3 () (unsigned-integer :bytes 3 :bits-per-byte 8)) +(define-binary-type u4 () (unsigned-integer :bytes 4 :bits-per-byte 8)) +(define-binary-type id3-tag-size () (unsigned-integer :bytes 4 :bits-per-byte 7)) + +;;; Strings + +(define-binary-type generic-string (length character-type) + (:reader (in) + (let ((string (make-string length))) + (dotimes (i length) + (setf (char string i) (read-value character-type in))) + string)) + (:writer (out string) + (dotimes (i length) + (write-value character-type out (char string i))))) + +(define-binary-type generic-terminated-string (terminator character-type) + (:reader (in) + (with-output-to-string (s) + (loop for char = (read-value character-type in) + until (char= char terminator) do (write-char char s)))) + (:writer (out string) + (loop for char across string + do (write-value character-type out char) + finally (write-value character-type out terminator)))) + +;;; ISO-8859-1 strings + +(define-binary-type iso-8859-1-char () + (:reader (in) + (let ((code (read-byte in))) + (or (code-char code) + (error "Character code ~d not supported" code)))) + (:writer (out char) + (let ((code (char-code char))) + (if (<= 0 code #xff) + (write-byte code out) + (error "Illegal character for iso-8859-1 encoding: character: ~c with code: ~d" char code))))) + +(define-binary-type iso-8859-1-string (length) + (generic-string :length length :character-type 'iso-8859-1-char)) + +(define-binary-type iso-8859-1-terminated-string (terminator) + (generic-terminated-string :terminator terminator :character-type 'iso-8859-1-char)) + +;;; UCS-2 (Unicode) strings (i.e. UTF-16 without surrogate pairs, phew.) + +;;; Define a binary type for reading a UCS-2 character relative to a +;;; particular byte ordering as indicated by the BOM value. + ;; v2.3 specifies that the BOM should be present. v2.2 is silent + ;; though it is arguably inherent in the definition of UCS-2) Length + ;; is in bytes. On the write side, since we don't have any way of + ;; knowing what BOM was used to read the string we just pick one. + ;; This does mean roundtrip transparency could be broken. + +(define-binary-type ucs-2-char (swap) + (:reader (in) + (let ((code (read-value 'u2 in))) + (when swap (setf code (swap-bytes code))) + (or (code-char code) (error "Character code ~d not supported" code)))) + (:writer (out char) + (let ((code (char-code char))) + (unless (<= 0 code #xffff) + (error "Illegal character for ucs-2 encoding: ~c with char-code: ~d" char code)) + (when swap (setf code (swap-bytes code))) + (write-value 'u2 out code)))) + +(defun swap-bytes (code) + (assert (<= code #xffff)) + (rotatef (ldb (byte 8 0) code) (ldb (byte 8 8) code)) + code) + + +(define-binary-type ucs-2-char-big-endian () (ucs-2-char :swap nil)) + +(define-binary-type ucs-2-char-little-endian () (ucs-2-char :swap t)) + +(defun ucs-2-char-type (byte-order-mark) + (ecase byte-order-mark + (#xfeff 'ucs-2-char-big-endian) + (#xfffe 'ucs-2-char-little-endian))) + +(define-binary-type ucs-2-string (length) + (:reader (in) + (let ((byte-order-mark (read-value 'u2 in)) + (characters (1- (/ length 2)))) + (read-value + 'generic-string in + :length characters + :character-type (ucs-2-char-type byte-order-mark)))) + (:writer (out string) + (write-value 'u2 out #xfeff) + (write-value + 'generic-string out string + :length (length string) + :character-type (ucs-2-char-type #xfeff)))) + +(define-binary-type ucs-2-terminated-string (terminator) + (:reader (in) + (let ((byte-order-mark (read-value 'u2 in))) + (read-value + 'generic-terminated-string in + :terminator terminator + :character-type (ucs-2-char-type byte-order-mark)))) + (:writer (out string) + (write-value 'u2 out #xfeff) + (write-value + 'generic-terminated-string out string + :terminator terminator + :character-type (ucs-2-char-type #xfeff)))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; ID3 tag class + +;;; Handle ID3v2.2 and ID3v2.3 (but not ID3v2.4 since it mostly just +;;; requires a bunch more string encoding foo.) (Well, we can mostly +;;; read v2.4 tags as v2.3 tags.) + +(define-tagged-binary-class id3-tag () + ((identifier (iso-8859-1-string :length 3)) + (major-version u1) + (revision u1) + (flags u1) + (size id3-tag-size)) + (:dispatch + (ecase major-version + (2 'id3v2.2-tag) + (3 'id3v2.3-tag)))) + +(define-binary-class id3v2.2-tag (id3-tag) + ((frames (id3-frames :tag-size size :frame-type 'id3v2.2-frame)))) + +(define-binary-class id3v2.3-tag (id3-tag) + ((extended-header-size (optional :type 'u4 :if (extended-p flags))) + (extra-flags (optional :type 'u2 :if (extended-p flags))) + (padding-size (optional :type 'u4 :if (extended-p flags))) + (crc (optional :type 'u4 :if (crc-p flags extra-flags))) + (frames (id3-frames :tag-size size :frame-type 'id3v2.3-frame)))) + + +(defun extended-p (flags) (logbitp 6 flags)) + +(defun crc-p (flags extra-flags) + (and (extended-p flags) (logbitp 15 extra-flags))) + +(define-binary-type optional (type if) + (:reader (in) + (when if (read-value type in))) + (:writer (out value) + (when if (write-value type out value)))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; ID3 frames + +(define-tagged-binary-class id3v2.2-frame () + ((id (frame-id :length 3)) + (size u3)) + (:dispatch (find-frame-class id))) + +(define-tagged-binary-class id3v2.3-frame () + ((id (frame-id :length 4)) + (size u4) + (flags u2) + (decompressed-size (optional :type 'u4 :if (frame-compressed-p flags))) + (encryption-scheme (optional :type 'u1 :if (frame-encrypted-p flags))) + (grouping-identity (optional :type 'u1 :if (frame-grouped-p flags)))) + (:dispatch (find-frame-class id))) + +(defun frame-compressed-p (flags) (logbitp 7 flags)) + +(defun frame-encrypted-p (flags) (logbitp 6 flags)) + +(defun frame-grouped-p (flags) (logbitp 5 flags)) + +;;; find-frame + +(defun find-frame-class (name) + (cond + ((and (char= (char name 0) #\T) + (not (member name '("TXX" "TXXX") :test #'string=))) + (ecase (length name) + (3 'text-info-frame-v2.2) + (4 'text-info-frame-v2.3))) + ((string= name "COM") 'comment-frame-v2.2) + ((string= name "COMM") 'comment-frame-v2.3) + (t + (ecase (length name) + (3 'generic-frame-v2.2) + (4 'generic-frame-v2.3))))) + +;;; id3-frames + +(define-binary-type id3-frames (tag-size frame-type) + (:reader (in) + (loop with to-read = tag-size + while (plusp to-read) + for frame = (read-frame frame-type in) + while frame + do (decf to-read (+ (frame-header-size frame) (size frame))) + collect frame + finally (loop repeat (1- to-read) do (read-byte in)))) + (:writer (out frames) + (loop with to-write = tag-size + for frame in frames + do (write-value frame-type out frame) + (decf to-write (+ (frame-header-size frame) (size frame))) + finally (loop repeat to-write do (write-byte 0 out))))) + +(defgeneric frame-header-size (frame)) + +(defmethod frame-header-size ((frame id3v2.2-frame)) 6) + +(defmethod frame-header-size ((frame id3v2.3-frame)) 10) + +(defun read-frame (frame-type in) + (handler-case (read-value frame-type in) + (in-padding () nil))) + +(define-condition in-padding () ()) + +(define-binary-type frame-id (length) + (:reader (in) + (let ((first-byte (read-byte in))) + (when (= first-byte 0) (signal 'in-padding)) + (let ((rest (read-value 'iso-8859-1-string in :length (1- length)))) + (concatenate + 'string (string (code-char first-byte)) rest)))) + (:writer (out id) + (write-value 'iso-8859-1-string out id :length length))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Generic frames + +(define-binary-class generic-frame () + ((data (raw-bytes :size (data-bytes (current-binary-object)))))) + +(defgeneric data-bytes (frame)) + +(defmethod data-bytes ((frame id3v2.2-frame)) + (size frame)) + +(defmethod data-bytes ((frame id3v2.3-frame)) + (let ((flags (flags frame))) + (- (size frame) + (if (frame-compressed-p flags) 4 0) + (if (frame-encrypted-p flags) 1 0) + (if (frame-grouped-p flags) 1 0)))) + + +(define-binary-class generic-frame-v2.2 (id3v2.2-frame generic-frame) ()) + +(define-binary-class generic-frame-v2.3 (id3v2.3-frame generic-frame) ()) + +(define-binary-type raw-bytes (size) + (:reader (in) + (let ((buf (make-array size :element-type '(unsigned-byte 8)))) + (read-sequence buf in) + buf)) + (:writer (out buf) + (write-sequence buf out))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Text info and comment frames + +(define-binary-class text-info-frame () + ((encoding u1) + (information (id3-encoded-string :encoding encoding :length (bytes-left 1))))) + +(define-binary-class comment-frame () + ((encoding u1) + (language (iso-8859-1-string :length 3)) + (description (id3-encoded-string :encoding encoding :terminator +null+)) + (text (id3-encoded-string + :encoding encoding + :length (bytes-left + (+ 1 ;; encoding + 3 ;; language + (encoded-string-length description encoding t))))))) + +(defun bytes-left (bytes-read) + (- (size (current-binary-object)) bytes-read)) + +(defun encoded-string-length (string encoding terminated) + (let ((characters (+ (length string) (if terminated 1 0)))) + (* characters (ecase encoding (0 1) (1 2))))) + +(defmethod (setf information) :after (value (frame text-info-frame)) + (declare (ignore value)) + (with-slots (encoding size information) frame + (setf size (encoded-string-length information encoding nil)))) + +(define-binary-class text-info-frame-v2.2 (id3v2.2-frame text-info-frame) ()) + +(define-binary-class text-info-frame-v2.3 (id3v2.3-frame text-info-frame) ()) + +(define-binary-class comment-frame-v2.2 (id3v2.2-frame comment-frame) ()) + +(define-binary-class comment-frame-v2.3 (id3v2.3-frame comment-frame) ()) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; ID3 encoded string + +(define-binary-type id3-encoded-string (encoding length terminator) + (:reader (in) + (multiple-value-bind (type keyword arg) + (string-args encoding length terminator) + (read-value type in keyword arg))) + (:writer (out string) + (multiple-value-bind (type keyword arg) + (string-args encoding length terminator) + (write-value type out string keyword arg)))) + +(defun string-args (encoding length terminator) + (cond + (length + (values (non-terminated-type encoding) :length length)) + (terminator + (values (terminated-type encoding) :terminator terminator)))) + +(defun non-terminated-type (encoding) + (ecase encoding + (0 'iso-8859-1-string) + (1 'ucs-2-string))) + +(defun terminated-type (encoding) + (ecase encoding + (0 'iso-8859-1-terminated-string) + (1 'ucs-2-terminated-string))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Application code + +(defun mp3-p (file) + (and + (not (directory-pathname-p file)) + (string-equal "mp3" (pathname-type file)))) + +(defun id3-p (file) + (with-open-file (in file) + (string= "ID3" (read-value 'iso-8859-1-string in :length 3)))) + +(defun read-id3 (file) + (with-open-file (in file :element-type '(unsigned-byte 8)) + (read-value 'id3-tag in))) + +(defun show-tag-header (file) + (with-slots (identifier major-version revision flags size) (read-id3 file) + (format t "~a ~d.~d ~8,'0b ~d bytes -- ~a~%" + identifier major-version revision flags size (enough-namestring file)))) + +(defun show-tag-headers (dir) + (walk-directory dir #'show-tag-header :test #'mp3-p)) + +(defun count-versions (dir) + (let ((versions (mapcar #'(lambda (x) (cons x 0)) '(2 3 4)))) + (flet ((count-version (file) + (incf (cdr (assoc (major-version (read-id3 file)) versions))))) + (walk-directory dir #'count-version :test #'mp3-p)) + versions)) + +(defun frame-types (file) + (delete-duplicates (mapcar #'id (frames (read-id3 file))) :test #'string=)) + +(defun frame-types-in-dir (dir) + (let ((ids ())) + (flet ((collect (file) + (setf ids (nunion ids (frame-types file) :test #'string=)))) + (walk-directory dir #'collect :test #'mp3-p)) + ids)) + +(defun frame-name-member (id) + (cond + ((member id '("COM" "COMM") :test #'string=) "Comment") + ((member id '("TAL" "TALB") :test #'string=) "Album") + ((member id '("TCM" "TCOM") :test #'string=) "Composer") + ((member id '("TCO" "TCON") :test #'string=) "Genre") + ((member id '("TEN" "TENC") :test #'string=) "Encoding program") + ((member id '("TP1" "TPE1") :test #'string=) "Artist") + ((member id '("TPA" "TPOS") :test #'string=) "Part of set") + ((member id '("TRK" "TRCK") :test #'string=) "Track") + ((member id '("TT2" "TIT2") :test #'string=) "Song") + ((member id '("TYE" "TYER") :test #'string=) "Year") + (t id))) + +;; As a hack in the ID3 format the string in a text info frame can +;; have an embedded null. Programs are not supposed to display any +;; information beyond the null. SUBSEQ and POSITION work together +;; nicely in this case since a NIL third argument to SUBSEQ is +;; equivalent to the length of the string. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Extracting information from ID3 tag + +(defun find-frame (id3 ids) + (find-if #'(lambda (x) (find (id x) ids :test #'string=)) (frames id3))) + +(defun get-text-info (id3 &rest ids) + (let ((frame (find-frame id3 ids))) + (when frame (upto-null (information frame))))) + +(defun upto-null (string) + (subseq string 0 (position +null+ string))) + +(defmethod information ((frame generic-frame-v2.3)) + (with-output-to-string (s) + (loop for byte across (data frame) do + (format s "~2,'0x" byte)))) + +(defun album (id3) (get-text-info id3 "TAL" "TALB")) + +(defun composer (id3) (get-text-info id3 "TCM" "TCOM")) + +(defun genre (id3) (get-text-info id3 "TCO" "TCON")) + +(defun encoding-program (id3) (get-text-info id3 "TEN" "TENC")) + +(defun artist (id3) (get-text-info id3 "TP1" "TPE1")) + +(defun part-of-set (id3) (get-text-info id3 "TPA" "TPOS")) + +(defun track (id3) (get-text-info id3 "TRK" "TRCK")) + +(defun song (id3) (get-text-info id3 "TT2" "TIT2")) + +(defun year (id3) (get-text-info id3 "TYE" "TYER" "TDRC")) + +;;; The first version of the ID3 format used a single byte to encode +;;; the genre. There were originally 80 official v1 genres. The makers +;;; of Winamp extended the list. + +(defun translated-genre (id3) + (let ((genre (genre id3))) + (if (and genre (char= #\( (char genre 0))) + (translate-v1-genre genre) + genre))) + +(defparameter *id3-v1-genres* + #( + ;; These are the official ID3v1 genres. + "Blues" "Classic Rock" "Country" "Dance" "Disco" "Funk" "Grunge" + "Hip-Hop" "Jazz" "Metal" "New Age" "Oldies" "Other" "Pop" "R&B" "Rap" + "Reggae" "Rock" "Techno" "Industrial" "Alternative" "Ska" + "Death Metal" "Pranks" "Soundtrack" "Euro-Techno" "Ambient" + "Trip-Hop" "Vocal" "Jazz+Funk" "Fusion" "Trance" "Classical" + "Instrumental" "Acid" "House" "Game" "Sound Clip" "Gospel" "Noise" + "AlternRock" "Bass" "Soul" "Punk" "Space" "Meditative" + "Instrumental Pop" "Instrumental Rock" "Ethnic" "Gothic" "Darkwave" + "Techno-Industrial" "Electronic" "Pop-Folk" "Eurodance" "Dream" + "Southern Rock" "Comedy" "Cult" "Gangsta" "Top 40" "Christian Rap" + "Pop/Funk" "Jungle" "Native American" "Cabaret" "New Wave" + "Psychadelic" "Rave" "Showtunes" "Trailer" "Lo-Fi" "Tribal" + "Acid Punk" "Acid Jazz" "Polka" "Retro" "Musical" "Rock & Roll" + "Hard Rock" + + ;; These were made up by the authors of Winamp but backported into + ;; the ID3 spec. + "Folk" "Folk-Rock" "National Folk" "Swing" "Fast Fusion" + "Bebob" "Latin" "Revival" "Celtic" "Bluegrass" "Avantgarde" + "Gothic Rock" "Progressive Rock" "Psychedelic Rock" "Symphonic Rock" + "Slow Rock" "Big Band" "Chorus" "Easy Listening" "Acoustic" "Humour" + "Speech" "Chanson" "Opera" "Chamber Music" "Sonata" "Symphony" + "Booty Bass" "Primus" "Porn Groove" "Satire" "Slow Jam" "Club" + "Tango" "Samba" "Folklore" "Ballad" "Power Ballad" "Rhythmic Soul" + "Freestyle" "Duet" "Punk Rock" "Drum Solo" "A capella" "Euro-House" + "Dance Hall" + + ;; These were also invented by the Winamp folks but ignored by the + ;; ID3 authors. + "Goa" "Drum & Bass" "Club-House" "Hardcore" "Terror" "Indie" + "BritPop" "Negerpunk" "Polsk Punk" "Beat" "Christian Gangsta Rap" + "Heavy Metal" "Black Metal" "Crossover" "Contemporary Christian" + "Christian Rock" "Merengue" "Salsa" "Thrash Metal" "Anime" "Jpop" + "Synthpop")) + + +(defun translate-v1-genre (genre) + (aref *id3-v1-genres* (parse-integer genre :start 1 :junk-allowed t))) + + + +;;; Local Variables: +;;; eval: (font-lock-add-keywords 'lisp-mode '(("(\\(define-binary-type\\)\\s +\\(\\(\\w\\|\\s_\\)+\\)" (1 font-lock-keyword-face) (2 font-lock-function-name-face)))) +;;; eval: (font-lock-add-keywords 'lisp-mode '(("(\\(define-binary-class\\)\\s +\\(\\(\\w\\|\\s_\\)+\\)" (1 font-lock-keyword-face) (2 font-lock-function-name-face)))) +;;; eval: (font-lock-add-keywords 'lisp-mode '(("(\\(define-tagged-binary-class\\)\\s +\\(\\(\\w\\|\\s_\\)+\\)" (1 font-lock-keyword-face) (2 font-lock-function-name-face)))) +;;; eval: (put 'define-binary-type 'common-lisp-indent-function '(6 4 &rest (&whole 2 4 2))) +;;; eval: (put 'define-binary-class 'common-lisp-indent-function (get 'defclass 'common-lisp-indent-function)) +;;; eval: (put 'define-tagged-binary-class 'common-lisp-indent-function (get 'defclass 'common-lisp-indent-function)) +;;; eval: (put 'walk-mp3s 'common-lisp-indent-function (get 'with-output-to-string 'common-lisp-indent-function)) +;;; End: + + diff --git a/practicals/Chapter25/packages.lisp b/practicals/Chapter25/packages.lisp new file mode 100644 index 0000000..130c880 --- /dev/null +++ b/practicals/Chapter25/packages.lisp @@ -0,0 +1,21 @@ +(in-package :cl-user) + +(defpackage :com.gigamonkeys.id3v2 + (:use :common-lisp + :com.gigamonkeys.binary-data + :com.gigamonkeys.pathnames) + (:export + :read-id3 + :mp3-p + :id3-p + :album + :composer + :genre + :encoding-program + :artist + :part-of-set + :track + :song + :year + :size + :translated-genre)) diff --git a/practicals/Chapter26/allegroserve.lisp b/practicals/Chapter26/allegroserve.lisp new file mode 100644 index 0000000..5089cc1 --- /dev/null +++ b/practicals/Chapter26/allegroserve.lisp @@ -0,0 +1,124 @@ +;;; This file contains the demonstration code used in Chapter 26. This +;;; file is not loaded as part of the url-function system. + +(require :aserve) + +(defpackage :com.gigamonkeys.web + (:use :cl :net.aserve :com.gigamonkeys.html :com.gigamonkeys.url-function)) + +(in-package :com.gigamonkeys.web) + +(start :port 2001) + +(publish :path "/random-number" :function 'random-number) + +(defun random-number (request entity) + (with-http-response (request entity :content-type "text/html") + (with-http-body (request entity) + (format + (request-reply-stream request) + "~@ + Random~@ + ~@ +

Random number: ~d

~@ + ~@ + ~@ + " + (random 1000))))) + +(defun random-number (request entity) + (with-http-response (request entity :content-type "text/html") + (with-http-body (request entity) + (with-html-output ((request-reply-stream request)) + (html + (:html + (:head (:title "Random")) + (:body + (:p "Random number: " (:print (random 1000)))))))))) + +(publish :path "/show-query-params" :function 'show-query-params) + +(defun show-query-params (request entity) + (with-http-response (request entity :content-type "text/html") + (with-http-body (request entity) + (with-html-output ((request-reply-stream request)) + (html + (:standard-page + (:title "Query Parameters") + (if (request-query request) + (html + (:table :border 1 + (loop for (k . v) in (request-query request) + do (html (:tr (:td k) (:td v)))))) + (html (:p "No query parameters."))))))))) + +(publish :path "/simple-form" :function 'simple-form) + +(defun simple-form (request entity) + (with-http-response (request entity :content-type "text/html") + (with-http-body (request entity) + (with-html-output ((request-reply-stream request)) + (html + (:html + (:head (:title "Simple Form")) + (:body + (:form :method "POST" :action "/show-query-params" + (:table + (:tr (:td "Foo") + (:td (:input :name "foo" :size 20))) + (:tr (:td "Password") + (:td (:input :name "password" :type "password" :size 20)))) + (:p (:input :name "submit" :type "submit" :value "Okay") + (:input ::type "reset" :value "Reset")))))))))) + +(defun random-number (request entity) + (with-http-response (request entity :content-type "text/html") + (with-http-body (request entity) + (with-html-output ((request-reply-stream request)) + (let* ((limit-string (or (request-query-value "limit" request) "")) + (limit (or (parse-integer limit-string :junk-allowed t) 1000))) + (html + (:html + (:head (:title "Random")) + (:body + (:p "Random number: " (:print (random limit))))))))))) + +(defun show-cookies (request entity) + (with-http-response (request entity :content-type "text/html") + (with-http-body (request entity) + (with-html-output ((request-reply-stream request)) + (html + (:standard-page + (:title "Cookies") + (if (null (get-cookie-values request)) + (html (:p "No cookies.")) + (html + (:table + (loop for (key . value) in (get-cookie-values request) + do (html (:tr (:td key) (:td value))))))))))))) + +(publish :path "/show-cookies" :function 'show-cookies) + + + +(defun set-cookie (request entity) + (with-http-response (request entity :content-type "text/html") + (set-cookie-header request :name "MyCookie" :value "A cookie value") + (with-http-body (request entity) + (with-html-output ((request-reply-stream request)) + (html + (:standard-page + (:title "Set Cookie") + (:p "Cookie set.") + (:p (:a :href "/show-cookies" "Look at cookie jar.")))))))) + +(publish :path "/set-cookie" :function 'set-cookie) + +(defmethod string->type ((type (eql 'integer)) value) + (parse-integer (or value "") :junk-allowed t)) + +(define-url-function random-number (request (limit integer 1000)) + (:html + (:head (:title "Random")) + (:body + (:p "Random number: " (:print (random limit)))))) diff --git a/practicals/Chapter26/html-infrastructure.lisp b/practicals/Chapter26/html-infrastructure.lisp new file mode 100644 index 0000000..587178b --- /dev/null +++ b/practicals/Chapter26/html-infrastructure.lisp @@ -0,0 +1,81 @@ +(in-package :com.gigamonkeys.url-function) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; API + +(defmacro define-url-function (name (request &rest params) &body body) + (with-gensyms (entity) + (let ((params (mapcar #'normalize-param params))) + `(progn + (defun ,name (,request ,entity) + (with-http-response (,request ,entity :content-type "text/html") + (let* (,@(param-bindings name request params)) + ,@(set-cookies-code name request params) + (with-http-body (,request ,entity) + (with-html-output ((request-reply-stream ,request)) + (html ,@body)))))) + (publish :path ,(format nil "/~(~a~)" name) :function ',name))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Compiler code + +(defun normalize-param (param) + (etypecase param + (list param) + (symbol `(,param string nil nil)))) + +(defun param-bindings (function-name request params) + (loop for param in params + collect (param-binding function-name request param))) + +(defun param-binding (function-name request param) + (destructuring-bind (name type &optional default sticky) param + (let ((query-name (symbol->query-name name)) + (cookie-name (symbol->cookie-name function-name name sticky))) + `(,name (or + (string->type ',type (request-query-value ,query-name ,request)) + ,@(if cookie-name + (list `(string->type ',type (get-cookie-value ,request ,cookie-name)))) + ,default))))) + +(defun symbol->query-name (sym) + (string-downcase sym)) + +(defun symbol->cookie-name (function-name sym sticky) + (let ((package-name (package-name (symbol-package function-name)))) + (when sticky + (ecase sticky + (:global + (string-downcase sym)) + (:package + (format nil "~(~a:~a~)" package-name sym)) + (:local + (format nil "~(~a:~a:~a~)" package-name function-name sym)))))) + +(defun set-cookies-code (function-name request params) + (loop for param in params + when (set-cookie-code function-name request param) collect it)) + +(defun set-cookie-code (function-name request param) + (destructuring-bind (name type &optional default sticky) param + (declare (ignore type default)) + (if sticky + `(when ,name + (set-cookie-header + ,request + :name ,(symbol->cookie-name function-name name sticky) + :value (princ-to-string ,name)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Runtime + +(defgeneric string->type (type value)) + +(defmethod string->type ((type (eql 'string)) value) + (and (plusp (length value)) value)) + +(defun get-cookie-value (request name) + (cdr (assoc name (get-cookie-values request) :test #'string=))) + + + diff --git a/practicals/Chapter26/packages.lisp b/practicals/Chapter26/packages.lisp new file mode 100644 index 0000000..be1953e --- /dev/null +++ b/practicals/Chapter26/packages.lisp @@ -0,0 +1,10 @@ +(in-package :cl-user) + +(defpackage :com.gigamonkeys.url-function + (:use :common-lisp + :net.aserve + :com.gigamonkeys.html + :com.gigamonkeys.macro-utilities) + (:export :define-url-function + :string->type)) + diff --git a/practicals/Chapter26/url-function.asd b/practicals/Chapter26/url-function.asd new file mode 100644 index 0000000..61d90d1 --- /dev/null +++ b/practicals/Chapter26/url-function.asd @@ -0,0 +1,19 @@ +(defpackage :com.gigamonkeys.url-function-system (:use :asdf :cl)) +(in-package :com.gigamonkeys.url-function-system) + +(require :aserve) + +(defsystem url-function + :name "url-function" + :author "Peter Seibel " + :version "0.1" + :maintainer "Peter Seibel " + :licence "BSD" + :description "define-url-function macro for AllegroServe" + :long-description "" + :components + ((:file "packages") + (:file "html-infrastructure" :depends-on ("packages"))) + :depends-on (:html :macro-utilities)) + + diff --git a/practicals/Chapter27/database.lisp b/practicals/Chapter27/database.lisp new file mode 100644 index 0000000..f583d98 --- /dev/null +++ b/practicals/Chapter27/database.lisp @@ -0,0 +1,282 @@ +(in-package :com.gigamonkeys.mp3-database) + +(defparameter *default-table-size* 100) + +(defclass table () + ((rows :accessor rows :initarg :rows :initform (make-rows)) + (schema :accessor schema :initarg :schema))) + +(defun make-rows (&optional (size *default-table-size*)) + (make-array size :adjustable t :fill-pointer 0)) + +(defclass column () + ((name + :reader name + :initarg :name) + (equality-predicate + :reader equality-predicate + :initarg :equality-predicate) + (comparator + :reader comparator + :initarg :comparator) + (default-value + :reader default-value + :initarg :default-value + :initform nil) + (value-normalizer + :reader value-normalizer + :initarg :value-normalizer + :initform #'(lambda (v column) (declare (ignore column)) v)))) + +(defclass interned-values-column (column) + ((interned-values + :reader interned-values + :initform (make-hash-table :test #'equal)) + (equality-predicate :initform #'eql) + (value-normalizer :initform #'intern-for-column))) + +(defun intern-for-column (value column) + (let ((hash (interned-values column))) + (or (gethash (not-nullable value column) hash) + (setf (gethash value hash) value)))) + +;;; Schemas + +(defgeneric make-column (name type &optional default-value)) + +(defun make-schema (spec) + (mapcar #'(lambda (column-spec) (apply #'make-column column-spec)) spec)) + +(defun find-column (column-name schema) + (or (find column-name schema :key #'name) + (error "No column: ~a in schema: ~a" column-name schema))) + +;;; Column constructors + +(defmethod make-column (name (type (eql 'string)) &optional default-value) + (make-instance + 'column + :name name + :comparator #'string< + :equality-predicate #'string= + :default-value default-value + :value-normalizer #'not-nullable)) + +(defmethod make-column (name (type (eql 'number)) &optional default-value) + (make-instance + 'column + :name name + :comparator #'< + :equality-predicate #'= + :default-value default-value)) + +(defmethod make-column (name (type (eql 'interned-string)) &optional default-value) + (make-instance + 'interned-values-column + :name name + :comparator #'string< + :default-value default-value)) + +(defun not-nullable (value column) + (or value (error "Column ~a can't be null" (name column)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; INSERT-ROW + +(defun insert-row (names-and-values table) + (vector-push-extend (normalize-row names-and-values (schema table)) (rows table))) + +(defun normalize-row (names-and-values schema) + (loop + for column in schema + for name = (name column) + for value = (or (getf names-and-values name) (default-value column)) + collect name + collect (normalize-for-column value column))) + +(defun normalize-for-column (value column) + (funcall (value-normalizer column) value column)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; SELECT + +(defun select (&key (columns t) from where distinct order-by) + (let ((rows (rows from)) + (schema (schema from))) + + (when where + (setf rows (restrict-rows rows where))) + + (unless (eql columns 't) + (setf schema (extract-schema (mklist columns) schema)) + (setf rows (project-columns rows schema))) + + (when distinct + (setf rows (distinct-rows rows schema))) + + (when order-by + (setf rows (sorted-rows rows schema (mklist order-by)))) + + (make-instance 'table :rows rows :schema schema))) + +(defun restrict-rows (rows where) + (remove-if-not where rows)) + +(defun project-columns (rows schema) + (map 'vector (extractor schema) rows)) + +(defun distinct-rows (rows schema) + (remove-duplicates rows :test (row-equality-tester schema))) + +(defun sorted-rows (rows schema order-by) + (sort (copy-seq rows) (row-comparator order-by schema))) + +;;; where-clause builders + +(defun matching (table &rest names-and-values) + "Build a where function that matches rows with the given column values." + (let ((matchers (column-matchers (schema table) names-and-values))) + #'(lambda (row) + (every #'(lambda (matcher) (funcall matcher row)) matchers)))) + +(defun column-matchers (schema names-and-values) + (loop for (name value) on names-and-values by #'cddr + when value collect + (column-matcher (find-column name schema) value))) + +(defun column-matcher (column value) + (let ((name (name column)) + (predicate (equality-predicate column)) + (normalized (normalize-for-column value column))) + #'(lambda (row) (funcall predicate (getf row name) normalized)))) + +(defun in (column-name table) + "Build a where function that matches rows in which the value of + the named column is in the given table" + (let ((test (equality-predicate (find-column column-name (schema table)))) + (values (map 'list #'(lambda (r) (getf r column-name)) (rows table)))) + #'(lambda (row) + (member (getf row column-name) values :test test)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Table info and utilities + +(defun column-value (row column-name) + (getf row column-name)) + +(defmacro do-rows ((row table) &body body) + `(loop for ,row across (rows ,table) do ,@body)) + +(defun map-rows (fn table) + (loop for row across (rows table) collect (funcall fn row))) + +(defun table-size (table) + (length (rows table))) + +(defun nth-row (n table) + (aref (rows table) n)) + +(defmacro with-column-values ((&rest vars) row &body body) + (once-only (row) + `(let ,(column-bindings vars row) ,@body))) + +(defun column-bindings (vars row) + (loop for v in vars collect `(,v (column-value ,row ,(as-keyword v))))) + +(defun as-keyword (symbol) + (intern (symbol-name symbol) :keyword)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; DELETE-ROWS, DELETE-ALL-ROWS + +(defun delete-rows (&key from where) + (loop + with rows = (rows from) + with store-idx = 0 + for read-idx from 0 + for row across rows + do (setf (aref rows read-idx) nil) + unless (funcall where row) do + (setf (aref rows store-idx) row) + (incf store-idx) + finally (setf (fill-pointer rows) store-idx))) + +(defun delete-all-rows (table) + (setf (rows table) (make-rows *default-table-size*))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; SORT-ROWS + +(defun sort-rows (table &rest column-names) + (setf (rows table) (sort (rows table) (row-comparator column-names (schema table)))) + table) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; RANDOM-SELECTION and SHUFFLE-TABLE + + +(defun shuffle-table (table) + (nshuffle-vector (rows table)) + table) + +(defun nshuffle-vector (vector) + "Shuffle a vector in place." + (loop for idx downfrom (1- (length vector)) to 1 + for other = (random (1+ idx)) + do (unless (= idx other) + (rotatef (aref vector idx) (aref vector other)))) + vector) + +(defun random-selection (table n) + (make-instance + 'table + :schema (schema table) + :rows (nshuffle-vector (random-sample (rows table) n)))) + +(defun random-sample (vector n) + "Based on Algorithm S from Knuth. TAOCP, vol. 2. p. 142" + (loop with selected = (make-array n :fill-pointer 0) + for idx from 0 + do + (loop + with to-select = (- n (length selected)) + for remaining = (- (length vector) idx) + while (>= (* remaining (random 1.0)) to-select) + do (incf idx)) + (vector-push (aref vector idx) selected) + when (= (length selected) n) return selected)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Helpers + +(defun mklist (thing) + (if (listp thing) thing (list thing))) + +(defun extract-schema (column-names schema) + (loop for c in column-names collect (find-column c schema))) + +(defun extractor (schema) + (let ((names (mapcar #'name schema))) + #'(lambda (row) + (loop for c in names collect c collect (getf row c))))) + +(defun row-equality-tester (schema) + (let ((names (mapcar #'name schema)) + (tests (mapcar #'equality-predicate schema))) + #'(lambda (a b) + (loop for name in names and test in tests + always (funcall test (getf a name) (getf b name)))))) + +(defun row-comparator (column-names schema) + (let ((comparators (mapcar #'comparator (extract-schema column-names schema)))) + #'(lambda (a b) + (loop + for name in column-names + for comparator in comparators + for a-value = (getf a name) + for b-value = (getf b name) + when (funcall comparator a-value b-value) return t + when (funcall comparator b-value a-value) return nil + finally (return nil))))) + + diff --git a/practicals/Chapter27/mp3-database.asd b/practicals/Chapter27/mp3-database.asd new file mode 100644 index 0000000..a66eb73 --- /dev/null +++ b/practicals/Chapter27/mp3-database.asd @@ -0,0 +1,18 @@ +(defpackage :com.gigamonkeys.mp3-database-system (:use :asdf :cl)) +(in-package :com.gigamonkeys.mp3-database-system) + +(defsystem mp3-database + :name "mp3-database" + :author "Peter Seibel " + :version "1.0" + :maintainer "Peter Seibel " + :licence "BSD" + :description "In-memory MP3 Database." + :long-description "" + :components + ((:file "packages") + (:file "database" :depends-on ("packages")) + (:file "mp3-database" :depends-on ("packages" "database"))) + :depends-on (:pathnames :macro-utilities :id3v2)) + + diff --git a/practicals/Chapter27/mp3-database.lisp b/practicals/Chapter27/mp3-database.lisp new file mode 100644 index 0000000..4aab49b --- /dev/null +++ b/practicals/Chapter27/mp3-database.lisp @@ -0,0 +1,46 @@ +(in-package :com.gigamonkeys.mp3-database) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Load database + +(defparameter *mp3-schema* + (make-schema + '((:file string) + (:genre interned-string "Unknown") + (:artist interned-string "Unknown") + (:album interned-string "Unknown") + (:song string) + (:track number 0) + (:year number 0) + (:id3-size number)))) + +(defparameter *mp3s* (make-instance 'table :schema *mp3-schema*)) + +(defun load-database (dir db) + (let ((count 0)) + (walk-directory + dir + #'(lambda (file) + (princ #\.) + (incf count) + (insert-row (file->row file) db)) + :test #'mp3-p) + (format t "~&Loaded ~d files into database." count))) + +(defun file->row (file) + (let ((id3 (read-id3 file))) + (list + :file (namestring (truename file)) + :genre (translated-genre id3) + :artist (artist id3) + :album (album id3) + :song (song id3) + :track (parse-track (track id3)) + :year (parse-year (year id3)) + :id3-size (size id3)))) + +(defun parse-track (track) + (when track (parse-integer track :end (position #\/ track)))) + +(defun parse-year (year) + (when year (parse-integer year))) diff --git a/practicals/Chapter27/packages.lisp b/practicals/Chapter27/packages.lisp new file mode 100644 index 0000000..928ed82 --- /dev/null +++ b/practicals/Chapter27/packages.lisp @@ -0,0 +1,33 @@ +(in-package :cl-user) + +(defpackage :com.gigamonkeys.mp3-database + (:use :common-lisp + :com.gigamonkeys.pathnames + :com.gigamonkeys.macro-utilities + :com.gigamonkeys.id3v2) + (:export :*default-table-size* + :*mp3-schema* + :*mp3s* + :column + :column-value + :delete-all-rows + :delete-rows + :do-rows + :extract-schema + :in + :insert-row + :load-database + :make-column + :make-schema + :map-rows + :matching + :not-nullable + :nth-row + :random-selection + :schema + :select + :shuffle-table + :sort-rows + :table + :table-size + :with-column-values)) diff --git a/practicals/Chapter28/packages.lisp b/practicals/Chapter28/packages.lisp new file mode 100644 index 0000000..b5e49fb --- /dev/null +++ b/practicals/Chapter28/packages.lisp @@ -0,0 +1,16 @@ +(in-package :cl-user) + +(defpackage :com.gigamonkeys.shoutcast + (:use :common-lisp + :net.aserve + :com.gigamonkeys.id3v2) + (:export :song + :file + :title + :id3-size + :find-song-source + :current-song + :still-current-p + :maybe-move-to-next-song + :*song-source-type*)) + diff --git a/practicals/Chapter28/shoutcast.asd b/practicals/Chapter28/shoutcast.asd new file mode 100644 index 0000000..8d653eb --- /dev/null +++ b/practicals/Chapter28/shoutcast.asd @@ -0,0 +1,20 @@ +(defpackage :com.gigamonkeys.shoutcast-system (:use :asdf :cl)) +(in-package :com.gigamonkeys.shoutcast-system) + +(require :aserve) + +(defsystem shoutcast + :name "shoutcast" + :author "Peter Seibel " + :version "0.1" + :maintainer "Peter Seibel " + :licence "BSD" + :description "Shoutcast server." + :long-description "Shoutcast server that runs in AllegroServe" + :components + ((:file "packages") + (:file "song-source" :depends-on ("packages")) + (:file "shoutcast" :depends-on ("packages"))) + :depends-on (:html :pathnames :macro-utilities :id3v2 :mp3-database :url-function)) + + diff --git a/practicals/Chapter28/shoutcast.lisp b/practicals/Chapter28/shoutcast.lisp new file mode 100644 index 0000000..eb8cc0a --- /dev/null +++ b/practicals/Chapter28/shoutcast.lisp @@ -0,0 +1,129 @@ +(in-package :com.gigamonkeys.shoutcast) + +(defparameter *metadata-interval* (expt 2 12)) +(defparameter *timeout-seconds* (* 60 60 24 7 52 10)) +(defparameter *song-source-type* 'singleton) + +(publish :path "/stream.mp3" :function 'shoutcast) + +(defun shoutcast (request entity) + (with-http-response + (request entity :content-type "audio/MP3" :timeout *timeout-seconds*) + (prepare-icy-response request *metadata-interval*) + (let ((wants-metadata-p (header-slot-value request :icy-metadata))) + (with-http-body (request entity) + (play-songs + (request-socket request) + (find-song-source *song-source-type* request) + (if wants-metadata-p *metadata-interval*)))))) + +(defun prepare-icy-response (request metadata-interval) + (setf (request-reply-protocol-string request) "ICY") + (loop for (k v) in (reverse + `((:|icy-metaint| ,(princ-to-string metadata-interval)) + (:|icy-notice1| "
This stream blah blah blah
") + (:|icy-notice2| "More blah") + (:|icy-name| "MyLispShoutcastServer") + (:|icy-genre| "Unknown") + (:|icy-url| ,(request-uri request)) + (:|icy-pub| "1"))) + do (setf (reply-header-slot-value request k) v)) + ;; iTunes, despite claiming to speak HTTP/1.1, doesn't understand + ;; chunked Transfer-encoding. Grrr. So we just turn it off. + (turn-off-chunked-transfer-encoding request)) + +(defun turn-off-chunked-transfer-encoding (request) + ;; We have to use a bit of knowledge about AllegroServe's internals + ;; to do this. + (setf (request-reply-strategy request) + (remove :chunked (request-reply-strategy request)))) + +(defun play-songs (stream song-source metadata-interval) + (handler-case + (loop + for next-metadata = metadata-interval + then (play-current + stream + song-source + next-metadata + metadata-interval) + while next-metadata) + (error (e) (format *trace-output* "Caught error in play-songs: ~a" e)))) + + +;;; Simple version of play current +(defun play-current (out song-source next-metadata metadata-interval) + (let ((song (current-song song-source))) + (when song + (let ((metadata (make-icy-metadata (title song)))) + (with-open-file (mp3 (file song)) + (unless (file-position mp3 (id3-size song)) + (error "Can't skip to position ~d in ~a" (id3-size song) (file song))) + (loop for byte = (read-byte mp3 nil nil) + while (and byte (still-current-p song song-source)) do + (write-byte byte out) + (decf next-metadata) + when (and (zerop next-metadata) metadata-interval) do + (write-sequence metadata out) + (setf next-metadata metadata-interval)) + + (maybe-move-to-next-song song song-source))) + next-metadata))) + +;;; i/o efficient version of play-current +#+(or) +(defun play-current (out song-source next-metadata metadata-interval) + (let ((song (current-song song-source))) + (when song + (let ((metadata (make-icy-metadata (title song))) + (buffer (make-array size :element-type '(unsigned-byte 8)))) + (with-open-file (mp3 (file song)) + (labels ((write-buffer (start end) + (if metadata-interval + (write-buffer-with-metadata start end) + (write-sequence buffer out :start start :end end))) + + (write-buffer-with-metadata (start end) + (cond + ((> next-metadata (- end start)) + (write-sequence buffer out :start start :end end) + (decf next-metadata (- end start))) + (t + (let ((middle (+ start next-metadata))) + (write-sequence buffer out :start start :end middle) + (write-sequence metadata out) + (setf next-metadata metadata-interval) + (write-buffer-with-metadata middle end)))))) + + (multiple-value-bind (skip-blocks skip-bytes) + (floor (id3-size song) (length buffer)) + + (unless (file-position mp3 (* skip-blocks (length buffer))) + (error "Couldn't skip over ~d ~d byte blocks." + skip-blocks (length buffer))) + + (loop for end = (read-sequence buffer mp3) + for start = skip-bytes then 0 + do (write-buffer start end) + while (and (= end (length buffer)) + (still-current-p song song-source))) + + (maybe-move-to-next-song song song-source))))) + next-metadata))) + +(defun make-icy-metadata (title) + (let* ((text (format nil "StreamTitle='~a';" (substitute #\Space #\' title))) + (blocks (ceiling (length text) 16)) + (buffer (make-array (1+ (* blocks 16)) + :element-type '(unsigned-byte 8) + :initial-element 0))) + (setf (aref buffer 0) blocks) + (loop + for char across text + for i from 1 + do (setf (aref buffer i) (char-code char))) + buffer)) + + + + diff --git a/practicals/Chapter28/song-source.lisp b/practicals/Chapter28/song-source.lisp new file mode 100644 index 0000000..4858b77 --- /dev/null +++ b/practicals/Chapter28/song-source.lisp @@ -0,0 +1,55 @@ +(in-package :com.gigamonkeys.shoutcast) + +(defclass song () + ((file :reader file :initarg :file) + (title :reader title :initarg :title) + (id3-size :reader id3-size :initarg :id3-size))) + +(defgeneric find-song-source (type request) + (:documentation "Find the song-source of the given type for the given request.")) + +(defgeneric current-song (source) + (:documentation "Return the currently playing song or NIL.")) + +(defgeneric still-current-p (song source) + (:documentation + "Return true if the song given is the same as the current-song.")) + +(defgeneric maybe-move-to-next-song (song source) + (:documentation + "If the given song is still the current one update the value +returned by current-song.")) + +;;; Singleton implementation + +(defclass simple-song-queue () + ((songs :accessor songs :initform (make-array 10 :adjustable t :fill-pointer 0)) + (index :accessor index :initform 0))) + +(defparameter *songs* (make-instance 'simple-song-queue)) + +(defmethod find-song-source ((type (eql 'singleton)) request) + (declare (ignore request)) + *songs*) + +(defmethod current-song ((source simple-song-queue)) + (when (array-in-bounds-p (songs source) (index source)) + (aref (songs source) (index source)))) + +(defmethod still-current-p (song (source simple-song-queue)) + (eql song (current-song source))) + +(defmethod maybe-move-to-next-song (song (source simple-song-queue)) + (when (still-current-p song source) + (incf (index source)))) + +(defun add-file-to-songs (file) + (vector-push-extend (file->song file) (songs *songs*))) + +(defun file->song (file) + (let ((id3 (read-id3 file))) + (make-instance + 'song + :file (namestring (truename file)) + :title (format nil "~a by ~a from ~a" (song id3) (artist id3) (album id3)) + :id3-size (size id3)))) diff --git a/practicals/Chapter29/mp3-browser.asd b/practicals/Chapter29/mp3-browser.asd new file mode 100644 index 0000000..261bdca --- /dev/null +++ b/practicals/Chapter29/mp3-browser.asd @@ -0,0 +1,24 @@ +(defpackage :com.gigamonkeys.mp3-browser-system (:use :asdf :cl)) +(in-package :com.gigamonkeys.mp3-browser-system) + +(require :aserve) + +(defclass css-file (static-file) ()) +(defmethod source-file-type ((c css-file) (s module)) "css") + +(defsystem mp3-browser + :name "mp3-browser" + :author "Peter Seibel " + :version "1.0" + :maintainer "Peter Seibel " + :licence "BSD" + :description "AllegroServe-based user interface for Shoutcast server." + :long-description "" + :components + ((:file "packages") + (:file "playlist" :depends-on ("packages")) + (:file "mp3-browser" :depends-on ("packages" "playlist")) + (:css-file "mp3-browser")) + :depends-on (:id3v2 :mp3-database :shoutcast :url-function :html)) + + diff --git a/practicals/Chapter29/mp3-browser.css b/practicals/Chapter29/mp3-browser.css new file mode 100644 index 0000000..2ef8340 --- /dev/null +++ b/practicals/Chapter29/mp3-browser.css @@ -0,0 +1,14 @@ +body { font-size: 10pt; font-family: sans-serif; } +h1.title { font-size: 18pt; } +table.playlist { width: 100%; font-size: 8pt; } +table.playlist tr { background-color: #dddddd; } +table.playlist tr.normal { background-color: #ffddff; } +table.playlist tr.now-playing { background-color: #ccbbee; } +table.playlist tr td { padding: 2pt; } +table.all-playlists { font-size: 10pt; } +table.all-playlists tr td + td { padding-left: 12pt; padding-right: 12pt; } +table.all-playlists td + td { text-align: center; } +tr:first-child { font-weight: bold; } +p.toolbar { font-weight: bold; text-align: center; } +p.playlist-toolbar { font-size: 9pt; text-align: center; } +p.footer { font-style: italic; text-align: right; } diff --git a/practicals/Chapter29/mp3-browser.lisp b/practicals/Chapter29/mp3-browser.lisp new file mode 100644 index 0000000..3483bfa --- /dev/null +++ b/practicals/Chapter29/mp3-browser.lisp @@ -0,0 +1,278 @@ +(in-package :com.gigamonkeys.mp3-browser) + +(defvar *major-version* 1) +(defvar *minor-version* 0) + +(defparameter *mp3-dir* nil) + +(defparameter *mp3-css* + (when *load-pathname* (make-pathname :name "mp3-browser" :type "css" :defaults *load-pathname*))) + +(defun configure-mp3-browser (&optional force) + (unless (or *mp3-dir* force) + (format t "Enter root directory of MP3 collection: ") + (force-output *standard-output*) + (setf *mp3-dir* (read))) + (unless (or *mp3-css* force) + (format t "Enter full filename of mp3-browser.css: ") + (force-output *standard-output*) + (setf *mp3-css* (read)))) + +(defun start-mp3-browser () + (unless (and *mp3-dir* *mp3-css*) + (configure-mp3-browser)) + (load-database *mp3-dir* *mp3s*) + (publish-file :path "/mp3-browser.css" :file *mp3-css* :content-type "text/css") + (setf *song-source-type* 'playlist) + (net.aserve::debug-on :notrap) + (net.aserve:start :port 2001)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Parameter types for url functions + +(defmethod string->type ((type (eql 'integer)) value) + (parse-integer (or value "") :junk-allowed t)) + +(defmethod string->type ((type (eql 'keyword)) value) + (and (plusp (length value)) (intern (string-upcase value) :keyword))) + +(defun safe-read-from-string (string) + (let ((*read-eval* nil)) (ignore-errors (read-from-string string)))) + +(defmethod string->type ((type (eql 'base-64-list)) value) + (let ((obj (base64->obj value))) + (if (listp obj) obj nil))) + +(defmacro with-safe-io-syntax (&body body) + `(with-standard-io-syntax + (let ((*read-eval* nil)) + ,@body))) + +(defun obj->base64 (obj) + (base64-encode (with-safe-io-syntax (write-to-string obj)))) + +(defun base64->obj (string) + (ignore-errors + (with-safe-io-syntax (read-from-string (base64-decode string))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Standard page layout + +(define-html-macro :mp3-browser-page ((&key title (header title)) &body body) + `(:html + (:head + (:title ,title) + (:link :rel "stylesheet" :type "text/css" :href "mp3-browser.css")) + (:body + (standard-header) + (when ,header (html (:h1 :class "title" ,header))) + ,@body + (standard-footer)))) + +(defun link (target &rest attributes) + (html + (:attribute + (:format "~a~@[?~{~(~a~)=~a~^&~}~]" target (mapcar #'urlencode attributes))))) + +(defun urlencode (string) + (net.aserve::encode-form-urlencoded string)) + +(defparameter *random-amount* 25) + +(defun standard-header () + (html + ((:p :class "toolbar") + "[" (:a :href (link "/browse" :what "genre") "All genres") "] " + "[" (:a :href (link "/browse" :what "genre" :random *random-amount*) "Random genres") "] " + "[" (:a :href (link "/browse" :what "artist") "All artists") "] " + "[" (:a :href (link "/browse":what "artist" :random *random-amount*) "Random artists") "] " + "[" (:a :href (link "/browse":what "album") "All albums") "] " + "[" (:a :href (link "/browse":what "album" :random *random-amount*) "Random albums") "] " + "[" (:a :href (link "/browse" :what "song" :random *random-amount*) "Random songs") "] " + "[" (:a :href (link "/playlist") "Playlist") "] " + "[" (:a :href (link "/all-playlists") "All playlists") "]"))) + +(defun standard-footer () + (html (:hr) ((:p :class "footer") "MP3 Browser v" *major-version* "." *minor-version*))) + +(define-html-macro :table-row (&attributes attrs &rest values) + `(:tr ,@attrs ,@(loop for v in values collect `(:td ,v)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; MP3 Browser + +(define-url-function browse + (request (what keyword :genre) genre artist album (random integer)) + + (let* ((values (values-for-page what genre artist album random)) + (title (browse-page-title what random genre artist album)) + (single-column (if (eql what :song) :file what)) + (values-string (values->base-64 single-column values))) + (html + (:mp3-browser-page + (:title title) + ((:form :method "POST" :action "playlist") + (:input :name "values" :type "hidden" :value values-string) + (:input :name "what" :type "hidden" :value single-column) + (:input :name "action" :type "hidden" :value :add-songs) + (:input :name "submit" :type "submit" :value "Add all")) + (:ul (do-rows (row values) (list-item-for-page what row))))))) + +(define-url-function playlist + (request + (playlist-id string (playlist-id request) :package) + (action keyword) ; Playlist manipulation action + (what keyword :file) ; for :add-songs action + (values base-64-list) ; " + file ; for :add-songs and :delete-songs actions + genre ; for :delete-songs action + artist ; " + album ; " + (order-by keyword) ; for :sort action + (shuffle keyword) ; for :shuffle action + (repeat keyword)) ; for :set-repeat action + + (let ((playlist (lookup-playlist playlist-id))) + (with-playlist-locked (playlist) + + (case action + (:add-songs (add-songs playlist what (or values (list file)))) + (:delete-songs (delete-songs + playlist + :file file :genre genre + :artist artist :album album)) + (:clear (clear-playlist playlist)) + (:sort (sort-playlist playlist order-by)) + (:shuffle (shuffle-playlist playlist shuffle)) + (:set-repeat (setf (repeat playlist) repeat))) + + (html + (:mp3-browser-page + (:title (:format "Playlist - ~a" (id playlist)) :header nil) + (playlist-toolbar playlist) + (if (empty-p playlist) + (html (:p (:i "Empty."))) + (html + ((:table :class "playlist") + (:table-row "#" "Song" "Album" "Artist" "Genre") + (let ((idx 0) + (current-idx (current-idx playlist))) + (do-rows (row (songs-table playlist)) + (with-column-values (track file song album artist genre) row + (let ((row-style (if (= idx current-idx) "now-playing" "normal"))) + (html + ((:table-row :class row-style) + track + (:progn song (delete-songs-link :file file)) + (:progn album (delete-songs-link :album album)) + (:progn artist (delete-songs-link :artist artist)) + (:progn genre (delete-songs-link :genre genre))))) + (incf idx)))))))))))) + +(define-url-function all-playlists (request) + (:mp3-browser-page + (:title "All Playlists") + ((:table :class "all-playlists") + (:table-row "Playlist" "# Songs" "Most recent user agent") + (with-process-lock (*playlists-lock*) + (loop for playlist being the hash-values of *playlists* do + (html + (:table-row + (:a :href (link "playlist" :playlist-id (id playlist)) (:print (id playlist))) + (:print (table-size (songs-table playlist))) + (:print (user-agent playlist))))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Helper functions + +(defun values-for-page (what genre artist album random) + (let ((values + (select + :from *mp3s* + :columns (if (eql what :song) t what) + :where (matching *mp3s* :genre genre :artist artist :album album) + :distinct (not (eql what :song)) + :order-by (if (eql what :song) '(:album :track) what)))) + (if random (random-selection values random) values))) + +(defun browse-page-title (what random genre artist album) + (with-output-to-string (s) + (when random (format s "~:(~r~) Random " random)) + (format s "~:(~a~p~)" what random) + (when (or genre artist album) + (when (not (eql what :song)) (princ " with songs" s)) + (when genre (format s " in genre ~a" genre)) + (when artist (format s " by artist ~a" artist)) + (when album (format s " on album ~a" album))))) + +(defun list-item-for-page (what row) + (if (eql what :song) + (with-column-values (song file album artist genre) row + (html + (:li + (:a :href (link "playlist" :file file :action "add-songs") (:b song)) " from " + (:a :href (link "browse" :what :song :album album) album) " by " + (:a :href (link "browse" :what :song :artist artist) artist) " in genre " + (:a :href (link "browse" :what :song :genre genre) genre)))) + (let ((value (column-value row what))) + (html + (:li value " - " + (browse-link :genre what value) + (browse-link :artist what value) + (browse-link :album what value) + (browse-link :song what value)))))) + +(defun browse-link (new-what what value) + (unless (eql new-what what) + (html + "[" + (:a :href (link "browse" :what new-what what value) (:format "~(~as~)" new-what)) + "] "))) + +(defun playlist-toolbar (playlist) + (let ((current-repeat (repeat playlist)) + (current-sort (ordering playlist)) + (current-shuffle (shuffle playlist))) + (html + (:p :class "playlist-toolbar" + (:i "Sort by:") + " [ " + (sort-playlist-button "genre" current-sort) " | " + (sort-playlist-button "artist" current-sort) " | " + (sort-playlist-button "album" current-sort) " | " + (sort-playlist-button "song" current-sort) " ] " + (:i "Shuffle by:") + " [ " + (playlist-shuffle-button "none" current-shuffle) " | " + (playlist-shuffle-button "song" current-shuffle) " | " + (playlist-shuffle-button "album" current-shuffle) " ] " + (:i "Repeat:") + " [ " + (playlist-repeat-button "none" current-repeat) " | " + (playlist-repeat-button "song" current-repeat) " | " + (playlist-repeat-button "all" current-repeat) " ] " + "[ " (:a :href (link "playlist" :action "clear") "Clear") " ] ")))) + +(defun playlist-button (action argument new-value current-value) + (let ((label (string-capitalize new-value))) + (if (string-equal new-value current-value) + (html (:b label)) + (html (:a :href (link "playlist" :action action argument new-value) label))))) + +(defun sort-playlist-button (order-by current-sort) + (playlist-button :sort :order-by order-by current-sort)) + +(defun playlist-shuffle-button (shuffle current-shuffle) + (playlist-button :shuffle :shuffle shuffle current-shuffle)) + +(defun playlist-repeat-button (repeat current-repeat) + (playlist-button :set-repeat :repeat repeat current-repeat)) + +(defun delete-songs-link (what value) + (html " [" (:a :href (link "playlist" :action :delete-songs what value) "x") "]")) + +(defun values->base-64 (column values-table) + (flet ((value (r) (column-value r column))) + (obj->base64 (map-rows #'value values-table)))) + + diff --git a/practicals/Chapter29/packages.lisp b/practicals/Chapter29/packages.lisp new file mode 100644 index 0000000..30dfe09 --- /dev/null +++ b/practicals/Chapter29/packages.lisp @@ -0,0 +1,19 @@ +(in-package :cl-user) + +(defpackage :com.gigamonkeys.mp3-browser + (:use :common-lisp + :net.aserve + :com.gigamonkeys.html + :com.gigamonkeys.shoutcast + :com.gigamonkeys.url-function + :com.gigamonkeys.mp3-database + :com.gigamonkeys.id3v2) + (:import-from :acl-socket + :ipaddr-to-dotted + :remote-host) + (:import-from :multiprocessing + :make-process-lock + :with-process-lock) + (:export :start-mp3-browser)) + + diff --git a/practicals/Chapter29/playlist.lisp b/practicals/Chapter29/playlist.lisp new file mode 100644 index 0000000..f1ceeff --- /dev/null +++ b/practicals/Chapter29/playlist.lisp @@ -0,0 +1,209 @@ +(in-package :com.gigamonkeys.mp3-browser) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Two versions of silence + +;; Set this variable to the filename of an MP3 of silence. +(defparameter *silence-mp3* nil) + +(defun make-silent-song (title &optional (file *silence-mp3*)) + (make-instance + 'song + :file file + :title title + :id3-size (if (id3-p file) (size (read-id3 file)) 0))) + +(defparameter *empty-playlist-song* (make-silent-song "Playlist empty.")) + +(defparameter *end-of-playlist-song* (make-silent-song "At end of playlist.")) + +(defclass playlist () + ((id :accessor id :initarg :id) + (songs-table :accessor songs-table :initform (make-playlist-table)) + (current-song :accessor current-song :initform *empty-playlist-song*) + (current-idx :accessor current-idx :initform 0) + (ordering :accessor ordering :initform :album) + (shuffle :accessor shuffle :initform :none) + (repeat :accessor repeat :initform :none) + (user-agent :accessor user-agent :initform "Unknown") + (lock :reader lock :initform (make-process-lock)))) + +(defun make-playlist-table () + (make-instance 'table :schema *mp3-schema*)) + +(defmacro with-playlist-locked ((playlist) &body body) + `(with-process-lock ((lock ,playlist)) + ,@body)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; find-song-source + +(defvar *playlists* (make-hash-table :test #'equal)) +(defparameter *playlists-lock* (make-process-lock :name "playlists-lock")) + +(defmethod find-song-source ((type (eql 'playlist)) request) + (let ((playlist (lookup-playlist (playlist-id request)))) + (with-playlist-locked (playlist) + (let ((user-agent (header-slot-value request :user-agent))) + (when user-agent (setf (user-agent playlist) user-agent)))) + playlist)) + +(defun lookup-playlist (id) + (with-process-lock (*playlists-lock*) + (or (gethash id *playlists*) + (setf (gethash id *playlists*) (make-instance 'playlist :id id))))) + +(defun playlist-id (request) + (ipaddr-to-dotted (remote-host (request-socket request)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; song-source implementation + +(defmethod current-song :around ((playlist playlist)) + (with-playlist-locked (playlist) (call-next-method))) + +(defmethod still-current-p (song (playlist playlist)) + (with-playlist-locked (playlist) + (eql song (current-song playlist)))) + +(defmethod maybe-move-to-next-song (song (playlist playlist)) + (with-playlist-locked (playlist) + (when (still-current-p song playlist) + (unless (at-end-p playlist) + (ecase (repeat playlist) + (:song) ; nothing changes + (:none (incf (current-idx playlist))) + (:all (setf (current-idx playlist) + (mod (1+ (current-idx playlist)) + (table-size (songs-table playlist))))))) + (update-current-if-necessary playlist)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Internals + +;;; update-current-if-necessary + +(defun update-current-if-necessary (playlist) + (unless (equal (file (current-song playlist)) + (file-for-current-idx playlist)) + (reset-current-song playlist))) + +(defun file-for-current-idx (playlist) + (if (at-end-p playlist) + nil + (column-value (nth-row (current-idx playlist) (songs-table playlist)) :file))) + +(defun at-end-p (playlist) + (>= (current-idx playlist) (table-size (songs-table playlist)))) + +(defun reset-current-song (playlist) + (setf + (current-song playlist) + (cond + ((empty-p playlist) *empty-playlist-song*) + ((at-end-p playlist) *end-of-playlist-song*) + (t (row->song (nth-row (current-idx playlist) (songs-table playlist))))))) + +(defun row->song (song-db-entry) + (with-column-values (file song artist album id3-size) song-db-entry + (make-instance + 'song + :file file + :title (format nil "~a by ~a from ~a" song artist album) + :id3-size id3-size))) + +(defun empty-p (playlist) + (zerop (table-size (songs-table playlist)))) + + +;;; Playlist manipulation functions called from mp3-browser.lisp + +(defun add-songs (playlist column-name values) + (let ((table (make-instance + 'table + :schema (extract-schema (list column-name) (schema *mp3s*))))) + (dolist (v values) (insert-row (list column-name v) table)) + (do-rows (row (select :from *mp3s* :where (in column-name table))) + (insert-row row (songs-table playlist)))) + (update-current-if-necessary playlist)) + +(defun delete-songs (playlist &rest names-and-values) + (delete-rows + :from (songs-table playlist) + :where (apply #'matching (songs-table playlist) names-and-values)) + (setf (current-idx playlist) (or (position-of-current playlist) 0)) + (update-current-if-necessary playlist)) + +(defun clear-playlist (playlist) + (delete-all-rows (songs-table playlist)) + (setf (current-idx playlist) 0) + (update-current-if-necessary playlist)) + +(defun sort-playlist (playlist ordering) + (setf (ordering playlist) ordering) + (setf (shuffle playlist) :none) + (order-playlist playlist) + (setf (current-idx playlist) (position-of-current playlist))) + +(defun shuffle-playlist (playlist shuffle) + (setf (shuffle playlist) shuffle) + (case shuffle + (:none (order-playlist playlist)) + (:song (shuffle-by-song playlist)) + (:album (shuffle-by-album playlist))) + (setf (current-idx playlist) (position-of-current playlist))) + +(defmethod (setf repeat) :after (value (playlist playlist)) + (if (and (at-end-p playlist) (not (empty-p playlist))) + (ecase value + (:song (setf (current-idx playlist) (1- (table-size (songs-table playlist))))) + (:none) + (:all (setf (current-idx playlist) 0))) + (update-current-if-necessary playlist))) + +;;; Shuffling helpers + +(defun position-of-current (playlist) + (let* ((table (songs-table playlist)) + (matcher (matching table :file (file (current-song playlist)))) + (pos 0)) + (do-rows (row table) + (when (funcall matcher row) + (return-from position-of-current pos)) + (incf pos)))) + +(defun order-playlist (playlist) + (apply #'sort-rows (songs-table playlist) + (case (ordering playlist) + (:genre '(:genre :album :track)) + (:artist '(:artist :album :track)) + (:album '(:album :track)) + (:song '(:song))))) + +(defun shuffle-by-song (playlist) + (shuffle-table (songs-table playlist))) + +(defun shuffle-by-album (playlist) + (let ((new-table (make-playlist-table))) + (do-rows (album-row (shuffled-album-names playlist)) + (do-rows (song (songs-for-album playlist (column-value album-row :album))) + (insert-row song new-table))) + (setf (songs-table playlist) new-table))) + +(defun shuffled-album-names (playlist) + (shuffle-table + (select + :columns :album + :from (songs-table playlist) + :distinct t))) + +(defun songs-for-album (playlist album) + (select + :from (songs-table playlist) + :where (matching (songs-table playlist) :album album) + :order-by :track)) + + + + + diff --git a/practicals/Chapter31/README.txt b/practicals/Chapter31/README.txt new file mode 100644 index 0000000..9a49dfc --- /dev/null +++ b/practicals/Chapter31/README.txt @@ -0,0 +1,8 @@ +The file css.lisp contains support for generating CSS output. To ues it add + + (:file "css" :depends-on ("packages" "html")) + +to html.asd and export :define-css-macro, :css, and :emit-css in packages.lisp. + +The file embed-foo-with-conditions-and-restarts.lisp contains the code discussed +in the sidebar in Chatper 30. diff --git a/practicals/Chapter31/css.lisp b/practicals/Chapter31/css.lisp new file mode 100644 index 0000000..46da69a --- /dev/null +++ b/practicals/Chapter31/css.lisp @@ -0,0 +1,74 @@ +(in-package #:com.gigamonkeys.html) + +;;; CSS support + +;; For stylesheets +(define-html-special-operator css-style (processor &rest body) + (dolist (sexp body) + (if (eql (first sexp) :import) + (emit-css-import processor sexp) + (process-css processor sexp)))) + +(defun emit-css-import (processor sexp) + (let ((url (second sexp))) + (freshline processor) + (raw-string processor "@import ") + (cond + ((consp url) + (raw-string processor "url(") + (raw-string processor (second url)) + (raw-string processor ")")) + (t (raw-string processor (format nil "\"~a\"" url)))) + (raw-string processor ";"))) + +(defun process-css (processor sexp) + (destructuring-bind (selector &rest attributes) sexp + (freshline processor) + (emit-css-selector processor selector) + (freshline processor) + (raw-string processor "{") + (indent processor) + (freshline processor) + (loop for (k v) on attributes by #'cddr do + (process-css-key-or-value processor k) + (raw-string processor ": ") + (process-css-key-or-value processor v) + (raw-string processor ";") + (freshline processor)) + (unindent processor) + (freshline processor) + (raw-string processor "}") + (freshline processor))) + +(defun emit-css-selector (processor selector) + (cond + ((atom selector) + (raw-string processor (string selector))) + ((and (consp selector) (member (first selector) '(or and adjacent))) + (loop with separator = (case (first selector) (or ", ") (and " ") (adjacent " + ")) + for (x . rest) on (rest selector) + do (emit-css-selector processor x) + when rest do (raw-string processor separator))) + (t + (multiple-value-bind (tag class pseudo-class id) (parse-selector selector) + (when tag + (embed-value processor (string tag))) + (when class + (embed-value processor (format nil ".~a" class))) + (when pseudo-class + (embed-value processor (format nil ":~a" pseudo-class))) + (when id + (embed-value processor (format nil "#~a" id))))))) + +(defun parse-selector (selector) + (if (member (first selector) '(:class :pseudo-class :id)) + (destructuring-bind (&key class pseudo-class id) selector + (values nil class pseudo-class id)) + (destructuring-bind (tag &key class pseudo-class id) selector + (values tag class pseudo-class id)))) + +(defun process-css-key-or-value (processor form) + (if (keywordp form) + (embed-value processor (string-downcase form)) + (process processor form))) + diff --git a/practicals/Chapter31/embed-foo-with-conditions-and-restarts.lisp b/practicals/Chapter31/embed-foo-with-conditions-and-restarts.lisp new file mode 100644 index 0000000..888c648 --- /dev/null +++ b/practicals/Chapter31/embed-foo-with-conditions-and-restarts.lisp @@ -0,0 +1,54 @@ +(in-package #:com.gigamonkeys.html) + +;; Conditions + +(define-condition embedded-lisp-in-interpreter (error) + ((form :initarg :form :reader form))) + +(define-condition value-in-interpreter (embedded-lisp-in-interpreter) () + (:report + (lambda (c s) + (format s "Can't embed values when interpreting. Value: ~s" (form c))))) + +(define-condition code-in-interpreter (embedded-lisp-in-interpreter) () + (:report + (lambda (c s) + (format s "Can't embed code when interpreting. Code: ~s" (form c))))) + +;; Implementation with restarts provided + +(defmethod embed-value ((pp html-pretty-printer) value) + (restart-case (error 'value-in-interpreter :form value) + (evaluate () + :report (lambda (s) (format s "EVAL ~s in null lexical environment." value)) + (raw-string pp (escape (princ-to-string (eval value)) *escapes*) t)))) + +(defmethod embed-code ((pp html-pretty-printer) code) + (restart-case (error 'code-in-interpreter :form code) + (evaluate () + :report (lambda (s) (format s "EVAL ~s in null lexical environment." code)) + (eval code)))) + +;; Restart functions + +(defun evaluate (&optional condition) + (declare (ignore condition)) + (invoke-restart 'evaluate)) + +(defun eval-dynamic-variables (&optional condition) + (when (and (symbolp (form condition)) (boundp (form condition))) + (evaluate))) + +(defun eval-code (&optional condition) + (when (consp (form condition)) + (evaluate))) + +;; Macro to automate binding of handlers to invoke evaluate restart. + +(defmacro with-dynamic-evaluation ((&key values code) &body body) + `(handler-bind ( + ,@(if values `((value-in-interpreter #'evaluate))) + ,@(if code `((code-in-interpreter #'evaluate)))) + ,@body)) + + diff --git a/practicals/Chapter31/html.asd b/practicals/Chapter31/html.asd new file mode 100644 index 0000000..2aee741 --- /dev/null +++ b/practicals/Chapter31/html.asd @@ -0,0 +1,17 @@ +(defpackage :com.gigamonkeys.html-system (:use :asdf :cl)) +(in-package :com.gigamonkeys.html-system) + +(defsystem html + :name "html" + :author "Peter Seibel " + :version "1.0" + :maintainer "Peter Seibel " + :licence "BSD" + :description "HTML and CSS generation from sexps." + :long-description "" + :components + ((:file "packages") + (:file "html" :depends-on ("packages")) + (:file "css" :depends-on ("packages" "html"))) + :depends-on (:macro-utilities)) + diff --git a/practicals/Chapter31/html.lisp b/practicals/Chapter31/html.lisp new file mode 100644 index 0000000..27e9589 --- /dev/null +++ b/practicals/Chapter31/html.lisp @@ -0,0 +1,492 @@ +(in-package #:com.gigamonkeys.html) + +(defvar *pretty* t) +(defvar *html-output* *standard-output*) +(defvar *html-pretty-printer* nil) + +(defparameter *xhtml* nil) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Public API + +(defmacro with-html-output ((stream &key (pretty *pretty*)) &body body) + `(let* ((*html-output* ,stream) + (*pretty* ,pretty)) + ,@body)) + +(defmacro with-html-to-file ((file &key (pretty *pretty*)) &body body) + (with-gensyms (stream) + `(with-open-file (,stream ,file :direction :output :if-exists :supersede) + (with-html-output (,stream :pretty ,pretty) + ,@body)))) + +(defmacro in-html-style (syntax) + (eval-when (:compile-toplevel :load-toplevel :execute) + (case syntax + (:html (setf *xhtml* nil)) + (:xhtml (setf *xhtml* t))))) + +(defun emit-html (sexp) (process (get-pretty-printer) sexp)) + +(defmacro html (&whole whole &body body) + (declare (ignore body)) + `(if *pretty* + (macrolet ((html (&body body) (codegen-html (sexp->ops body) t))) + (let ((*html-pretty-printer* (get-pretty-printer))) ,whole)) + (macrolet ((html (&body body) (codegen-html (sexp->ops body) nil))) + ,whole))) + +;;; Helpers for public API + +(defun get-pretty-printer () + (or *html-pretty-printer* + (make-instance + 'html-pretty-printer + :printer (make-instance 'indenting-printer :out *html-output*)))) + +(defun codegen-html (ops pretty) + (let ((*pretty* pretty)) + `(progn ,@(generate-code (optimize-static-output ops)) nil))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; String escaping + +(defparameter *element-escapes* "<>&") +(defparameter *attribute-escapes* "<>&\"'") +(defvar *escapes* *element-escapes*) + +(defun escape-char (char) + (case char + (#\& "&") + (#\< "<") + (#\> ">") + (#\' "'") + (#\" """) + (t (format nil "&#~d;" (char-code char))))) + +(defun escape (in to-escape) + (flet ((needs-escape-p (char) (find char to-escape))) + (with-output-to-string (out) + (loop for start = 0 then (1+ pos) + for pos = (position-if #'needs-escape-p in :start start) + do (write-sequence in out :start start :end pos) + when pos do (write-sequence (escape-char (char in pos)) out) + while pos)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; indenting-printer + +(defclass indenting-printer () + ((out :accessor out :initarg :out) + (beginning-of-line-p :accessor beginning-of-line-p :initform t) + (indentation :accessor indentation :initform 0) + (indenting-p :accessor indenting-p :initform t))) + +(defun emit (ip string) + (loop for start = 0 then (1+ pos) + for pos = (position #\Newline string :start start) + do (emit/no-newlines ip string :start start :end pos) + when pos do (emit-newline ip) + while pos)) + +(defun emit/no-newlines (ip string &key (start 0) end) + (indent-if-necessary ip) + (write-sequence string (out ip) :start start :end end) + (unless (zerop (- (or end (length string)) start)) + (setf (beginning-of-line-p ip) nil))) + +(defun emit-newline (ip) + (write-char #\Newline (out ip)) + (setf (beginning-of-line-p ip) t)) + +(defun emit-freshline (ip) + (unless (beginning-of-line-p ip) (emit-newline ip))) + +(defun indent-if-necessary (ip) + (when (and (beginning-of-line-p ip) (indenting-p ip)) + (loop repeat (indentation ip) do (write-char #\Space (out ip))) + (setf (beginning-of-line-p ip) nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; html processor interface + +(defgeneric raw-string (processor string &optional check-for-newlines)) + +(defgeneric newline (processor)) + +(defgeneric freshline (processor)) + +(defgeneric indent (processor)) + +(defgeneric unindent (processor)) + +(defgeneric toggle-indenting (processor)) + +(defgeneric embed-value (processor value)) + +(defgeneric embed-code (processor code)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; html-pretty-printer + +(defclass html-pretty-printer () + ((printer :accessor printer :initarg :printer) + (tab-width :accessor tab-width :initarg :tab-width :initform 2))) + +(defmethod raw-string ((pp html-pretty-printer) string &optional newlines-p) + (if newlines-p + (emit (printer pp) string) + (emit/no-newlines (printer pp) string))) + +(defmethod newline ((pp html-pretty-printer)) + (emit-newline (printer pp))) + +(defmethod freshline ((pp html-pretty-printer)) + (when *pretty* (emit-freshline (printer pp)))) + +(defmethod indent ((pp html-pretty-printer)) + (when *pretty* + (incf (indentation (printer pp)) (tab-width pp)))) + +(defmethod unindent ((pp html-pretty-printer)) + (when *pretty* + (decf (indentation (printer pp)) (tab-width pp)))) + +(defmethod toggle-indenting ((pp html-pretty-printer)) + (when *pretty* + (with-slots (indenting-p) (printer pp) + (setf indenting-p (not indenting-p))))) + +(defmethod embed-value ((pp html-pretty-printer) value) + (error "Can't embed values when interpreting. Value: ~s" value)) + +(defmethod embed-code ((pp html-pretty-printer) code) + (error "Can't embed code when interpreting. Code: ~s" code)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Ops buffer + +(defun make-op-buffer () (make-array 10 :adjustable t :fill-pointer 0)) + +(defun push-op (op ops-buffer) (vector-push-extend op ops-buffer)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Compiler + +(defclass html-compiler () + ((ops :accessor ops :initform (make-op-buffer)))) + +(defmethod raw-string ((compiler html-compiler) string &optional newlines-p) + (push-op `(:raw-string ,string ,newlines-p) (ops compiler))) + +(defmethod newline ((compiler html-compiler)) + (push-op '(:newline) (ops compiler))) + +(defmethod freshline ((compiler html-compiler)) + (push-op '(:freshline) (ops compiler))) + +(defmethod indent ((compiler html-compiler)) + (push-op `(:indent) (ops compiler))) + +(defmethod unindent ((compiler html-compiler)) + (push-op `(:unindent) (ops compiler))) + +(defmethod toggle-indenting ((compiler html-compiler)) + (push-op `(:toggle-indenting) (ops compiler))) + +(defmethod embed-value ((compiler html-compiler) value) + (push-op `(:embed-value ,value ,*escapes*) (ops compiler))) + +(defmethod embed-code ((compiler html-compiler) code) + (push-op `(:embed-code ,code) (ops compiler))) + +(defun sexp->ops (body) + (loop with compiler = (make-instance 'html-compiler) + for form in body do (process compiler form) + finally (return (ops compiler)))) + +(defun optimize-static-output (ops) + (let ((new-ops (make-op-buffer))) + (with-output-to-string (buf) + (flet ((add-op (op) + (compile-buffer buf new-ops) + (push-op op new-ops))) + (loop for op across ops do + (ecase (first op) + (:raw-string (write-sequence (second op) buf)) + ((:newline :embed-value :embed-code) (add-op op)) + ((:indent :unindent :freshline :toggle-indenting) + (when *pretty* (add-op op))))) + (compile-buffer buf new-ops))) + new-ops)) + +(defun compile-buffer (buf ops) + "Compile a string possibly containing newlines into a sequence of +:raw-string and :newline ops." + (loop with str = (get-output-stream-string buf) + for start = 0 then (1+ pos) + for pos = (position #\Newline str :start start) + when (< start (length str)) + do (push-op `(:raw-string ,(subseq str start pos) nil) ops) + when pos do (push-op '(:newline) ops) + while pos)) + +(defun generate-code (ops) + (loop for op across ops collect (apply #'op->code op))) + +(defgeneric op->code (op &rest operands)) + +(defmethod op->code ((op (eql :raw-string)) &rest operands) + (destructuring-bind (string check-for-newlines) operands + (if *pretty* + `(raw-string *html-pretty-printer* ,string ,check-for-newlines) + `(write-sequence ,string *html-output*)))) + +(defmethod op->code ((op (eql :newline)) &rest operands) + (if *pretty* + `(newline *html-pretty-printer*) + `(write-char #\Newline *html-output*))) + +(defmethod op->code ((op (eql :freshline)) &rest operands) + (if *pretty* + `(freshline *html-pretty-printer*) + (error "Bad op when not pretty-printing: ~a" op))) + +(defmethod op->code ((op (eql :indent)) &rest operands) + (if *pretty* + `(indent *html-pretty-printer*) + (error "Bad op when not pretty-printing: ~a" op))) + +(defmethod op->code ((op (eql :unindent)) &rest operands) + (if *pretty* + `(unindent *html-pretty-printer*) + (error "Bad op when not pretty-printing: ~a" op))) + +(defmethod op->code ((op (eql :toggle-indenting)) &rest operands) + (if *pretty* + `(toggle-indenting *html-pretty-printer*) + (error "Bad op when not pretty-printing: ~a" op))) + +(defmethod op->code ((op (eql :embed-value)) &rest operands) + (destructuring-bind (value escapes) operands + (if *pretty* + (if escapes + `(raw-string *html-pretty-printer* (escape (princ-to-string ,value) ,escapes) t) + `(raw-string *html-pretty-printer* (princ-to-string ,value) t)) + (if escapes + `(write-sequence (escape (princ-to-string ,value) ,escapes) *html-output*) + `(princ ,value *html-output*))))) + +(defmethod op->code ((op (eql :embed-code)) &rest operands) + (first operands)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; HTML processor. + +(defun process (processor form) + (cond + ((special-form-p form) (process-special-form processor form)) + ((macro-form-p form) (process processor (expand-macro-form form))) + ((sexp-html-p form) (process-sexp-html processor form)) + ((consp form) (embed-code processor form)) + (t (embed-value processor form)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Language syntax + +(defun sexp-html-p (form) + (or (self-evaluating-p form) (cons-form-p form))) + +(defun self-evaluating-p (form) + (and (atom form) (if (symbolp form) (keywordp form) t))) + +(defun cons-form-p (form &optional (test #'keywordp)) + (and (consp form) + (or (funcall test (car form)) + (and (consp (car form)) (funcall test (caar form)))))) + +(defun macro-form-p (form) + (cons-form-p form #'(lambda (x) (and (symbolp x) (get x 'html-macro))))) + +(defun special-form-p (form) + (and (consp form) (symbolp (car form)) (get (car form) 'html-special-operator))) + +(defun parse-cons-form (sexp) + (if (consp (first sexp)) + (parse-explicit-attributes-sexp sexp) + (parse-implicit-attributes-sexp sexp))) + +(defun parse-explicit-attributes-sexp (sexp) + (destructuring-bind ((tag &rest attributes) &body body) sexp + (values tag attributes body))) + +(defun parse-implicit-attributes-sexp (sexp) + (loop with tag = (first sexp) + for rest on (rest sexp) by #'cddr + while (and (keywordp (first rest)) (second rest)) + when (second rest) + collect (first rest) into attributes and + collect (second rest) into attributes + end + finally (return (values tag attributes rest)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; SEXP-HTML + +(defparameter *block-elements* + '(:body :colgroup :dl :fieldset :form :head :html :map :noscript :object + :ol :optgroup :pre :script :select :style :table :tbody :tfoot :thead + :tr :ul)) + +(defparameter *paragraph-elements* + '(:area :base :blockquote :br :button :caption :col :dd :div :dt :h1 + :h2 :h3 :h4 :h5 :h6 :hr :input :li :link :meta :option :p :param + :td :textarea :th :title)) + +(defparameter *inline-elements* + '(:a :abbr :acronym :address :b :bdo :big :cite :code :del :dfn :em + :i :img :ins :kbd :label :legend :q :samp :small :span :strong :sub + :sup :tt :var)) + +(defparameter *empty-elements* + '(:area :base :br :col :hr :img :input :link :meta :param)) + +(defparameter *preserve-whitespace-elements* '(:pre :script :style)) + +(defun process-sexp-html (processor form) + (if (self-evaluating-p form) + (raw-string processor (escape (princ-to-string form) *escapes*) t) + (process-cons-sexp-html processor form))) + +(defun process-cons-sexp-html (processor form) + (when (string= *escapes* *attribute-escapes*) + (error "Can't use cons forms in attributes: ~a" form)) + (multiple-value-bind (tag attributes body) (parse-cons-form form) + (emit-open-tag processor tag body attributes) + (emit-element-body processor tag body) + (emit-close-tag processor tag body))) + +(defun emit-open-tag (processor tag body-p attributes) + (when (or (paragraph-element-p tag) (block-element-p tag)) + (freshline processor)) + (raw-string processor (format nil "<~(~a~)" tag)) + (emit-attributes processor attributes) + (raw-string processor (if (and *xhtml* (not body-p)) "/>" ">"))) + +(defun emit-attributes (processor attributes) + (loop for (k v) on attributes by #'cddr do + (raw-string processor (format nil " ~(~a~)='" k)) + (let ((*escapes* *attribute-escapes*)) + (process processor (if (eql v t) (string-downcase k) v))) + (raw-string processor "'"))) + +(defun emit-element-body (processor tag body) + (when (block-element-p tag) + (freshline processor) + (indent processor)) + (when (preserve-whitespace-p tag) (toggle-indenting processor)) + (dolist (item body) (process processor item)) + (when (preserve-whitespace-p tag) (toggle-indenting processor)) + (when (block-element-p tag) + (unindent processor) + (freshline processor))) + +(defun emit-close-tag (processor tag body-p) + (unless (and (or *xhtml* (empty-element-p tag)) (not body-p)) + (raw-string processor (format nil "" tag))) + (when (or (paragraph-element-p tag) (block-element-p tag)) + (freshline processor))) + +(defun block-element-p (tag) (find tag *block-elements*)) + +(defun paragraph-element-p (tag) (find tag *paragraph-elements*)) + +(defun empty-element-p (tag) (find tag *empty-elements*)) + +(defun preserve-whitespace-p (tag) (find tag *preserve-whitespace-elements*)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Special operators + +(defmacro define-html-special-operator (name (processor &rest other-parameters) &body body) + `(eval-when (:compile-toplevel :load-toplevel :execute) + (setf (get ',name 'html-special-operator) + (lambda (,processor ,@other-parameters) ,@body)))) + +(defun process-special-form (processor form) + (apply (get (car form) 'html-special-operator) processor (rest form))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Macros + +(defmacro define-html-macro (name (&rest args) &body body) + (multiple-value-bind (attribute-var args) + (parse-html-macro-lambda-list args) + (if attribute-var + (generate-macro-with-attributes name attribute-var args body) + (generate-macro-no-attributes name args body)))) + +(defun generate-macro-with-attributes (name attribute-args args body) + (with-gensyms (attributes form-body) + (if (symbolp attribute-args) (setf attribute-args `(&rest ,attribute-args))) + `(eval-when (:compile-toplevel :load-toplevel :execute) + (setf (get ',name 'html-macro-wants-attributes) t) + (setf (get ',name 'html-macro) + (lambda (,attributes ,form-body) + (destructuring-bind (,@attribute-args) ,attributes + (destructuring-bind (,@args) ,form-body + ,@body))))))) + +(defun generate-macro-no-attributes (name args body) + (with-gensyms (form-body) + `(eval-when (:compile-toplevel :load-toplevel :execute) + (setf (get ',name 'html-macro-wants-attributes) nil) + (setf (get ',name 'html-macro) + (lambda (,form-body) + (destructuring-bind (,@args) ,form-body ,@body)))))) + +(defun parse-html-macro-lambda-list (args) + "Parse a lambda list that can include the &attributes lambda-list-keyword." + (let ((attr-cons (member '&attributes args))) + (values + (cadr attr-cons) + (nconc (ldiff args attr-cons) (cddr attr-cons))))) + +(defun expand-macro-form (form) + (if (or (consp (first form)) + (get (first form) 'html-macro-wants-attributes)) + (multiple-value-bind (tag attributes body) (parse-cons-form form) + (funcall (get tag 'html-macro) attributes body)) + (destructuring-bind (tag &body body) form + (funcall (get tag 'html-macro) body)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Special Forms + +(define-html-special-operator :print (processor form) + (cond + ((self-evaluating-p form) + (warn "Redundant :print of self-evaluating form ~s" form) + (process-sexp-html processor form)) + (t + (embed-value processor form)))) + +(define-html-special-operator :format (processor &rest args) + (if (every #'self-evaluating-p args) + (process-sexp-html processor (apply #'format nil args)) + (embed-value processor `(format nil ,@args)))) + +(define-html-special-operator :progn (processor &rest body) + (loop for exp in body do (process processor exp))) + +(define-html-special-operator :noescape (processor &rest body) + (let ((*escapes* nil)) + (loop for exp in body do (process processor exp)))) + +(define-html-special-operator :attribute (processor &rest body) + (let ((*escapes* *attribute-escapes*)) + (loop for exp in body do (process processor exp)))) + +(define-html-special-operator :newline (processor) + (newline processor)) diff --git a/practicals/Chapter31/packages.lisp b/practicals/Chapter31/packages.lisp new file mode 100644 index 0000000..8d6e7b2 --- /dev/null +++ b/practicals/Chapter31/packages.lisp @@ -0,0 +1,14 @@ +(in-package :cl-user) + +(defpackage :com.gigamonkeys.html + (:use :common-lisp :com.gigamonkeys.macro-utilities) + (:export :with-html-output + :with-html-to-file + :in-html-style + :define-html-macro + :define-css-macro + :css + :html + :emit-css + :emit-html + :&attributes)) diff --git a/practicals/Chapter32/profiler.lisp b/practicals/Chapter32/profiler.lisp new file mode 100644 index 0000000..3efb076 --- /dev/null +++ b/practicals/Chapter32/profiler.lisp @@ -0,0 +1,37 @@ +(in-package :cl-user) + +(defparameter *timing-data* ()) + +(defmacro with-timing (label &body body) + (with-gensyms (start) + `(let ((,start (get-internal-run-time))) + (unwind-protect (progn ,@body) + (push (list ',label ,start (get-internal-run-time)) *timing-data*))))) + +(defun clear-timing-data () + (setf *timing-data* ())) + +(defun show-timing-data () + (loop for (label time count time-per %-of-total) in (compile-timing-data) do + (format t "~3d% ~a: ~d ticks over ~d calls for ~d per.~%" + %-of-total label time count time-per))) + +(defun compile-timing-data () + (loop with timing-table = (make-hash-table) + with count-table = (make-hash-table) + for (label start end) in *timing-data* + for time = (- end start) + summing time into total + do + (incf (gethash label timing-table 0) time) + (incf (gethash label count-table 0)) + finally + (return + (sort + (loop for label being the hash-keys in timing-table collect + (let ((time (gethash label timing-table)) + (count (gethash label count-table))) + (list label time count (round (/ time count)) (round (* 100 (/ time total)))))) + #'> :key #'fifth)))) + + diff --git a/practicals/LICENSE b/practicals/LICENSE new file mode 100644 index 0000000..450c5ef --- /dev/null +++ b/practicals/LICENSE @@ -0,0 +1,29 @@ +Copyright (c) 2005, Peter Seibel All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the Peter Seibel nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/practicals/README.txt b/practicals/README.txt new file mode 100644 index 0000000..e3cdce0 --- /dev/null +++ b/practicals/README.txt @@ -0,0 +1,46 @@ +This directory contains the source code for _Practical Common Lisp_. You may use +and redestribute this software the terms of the license in file LICENSE. + +The code is designed to be loaded with Another System Definition Facility (ASDF) +and each chapter directory contains its own ASD file. You can either add the +name of each ChapterXX directory to ASDF:*CENTRAL-REGISTRY* or you can create +symlinks to the ASD files in those directories in a directory that is already +named in ASDF:*CENTRAL-REGISTRY*. If you also add this directory to the central +registry or create a symlink to the file practicals.asd, you can then load all +the practicals code by typing: + + (asdf:oos 'asdf:load-op :practicals) + +at the REPL. You can also load the code for individual chapters by loading the +system of the same name as the ASD file in each ChapterXX directory. + + ./Chapter03/simple-database.asd + ./Chapter08/macro-utilities.asd + ./Chapter09/test-framework.asd + ./Chapter15/pathnames.asd + ./Chapter23/spam.asd + ./Chapter24/binary-data.asd + ./Chapter25/id3v2.asd + ./Chapter26/url-function.asd + ./Chapter27/mp3-database.asd + ./Chapter28/shoutcast.asd + ./Chapter29/mp3-browser.asd + ./Chapter31/html.asd + +Thus to load the test framework code from Chapter 9, you'd type: + + (asdf:oos 'asdf:load-op :test-framework) + +at the REPL. (Note that Chapter31/ contains the code for both Chapters 30 and +31.) + +Alternatively, you can download the Practical Common Lisp, Lisp in a Box +distribution from: + + http://www.gigamonkeys.com/book/lispbox/ + +which provides the easy-to install Emacs + SLIME Lisp development environment +discussed in the book. That distribution contains all the book's code already +set up to be loaded with ASDF. + +--Peter Seibel diff --git a/practicals/libraries/cl-ppcre-1.2.3/CHANGELOG b/practicals/libraries/cl-ppcre-1.2.3/CHANGELOG new file mode 100644 index 0000000..ee42cb7 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/CHANGELOG @@ -0,0 +1,236 @@ +Version 1.2.3 +2005-02-02 +Wrapped WITH-COMPILATION-UNIT around loop in load.lisp + +Version 1.2.2 +2005-02-02 +Fixed bug in hash table optimization (introduced in 1.1.0) + +Version 1.2.1 +2005-01-25 +There was a wrong read-time conditional in api.lisp, sorry + +Version 1.2.0 +2005-01-24 +AllegroCL compatibility mode +Fixed broken load.lisp file (caught by Jim Prewett and Zach Beane) + +Version 1.1.0 +2005-01-23 +Cleaned up load.lisp and cl-ppcre.asd +Make large hash tables smaller, if possible +Correct treatment of constant regular expressions in DO-SCANS + +Version 1.0.0 +2004-12-22 +Special anniversary release... :) + +Version 0.9.4 +2004-12-18 +Fixed bug in NORMALIZE-VAR-LIST (caught by Dave Roberts) + +Version 0.9.3 +2004-12-09 +Fixed bug in CREATE-SCANNER-AUX (caught by Allan Ruttenberg and Gary Byers) + +Version 0.9.2 +2004-12-06 +More compiler macros (thanks to Allan Ruttenberg) + +Version 0.9.1 +2004-11-29 +Shortcuts for REGISTER-GROUPS-BIND and DO-REGISTER-GROUPS (suggested by Alexander Kjeldaas) + +Version 0.9.0 +2004-10-14 +Experimental support for "filters" +Bugfix for standalone regular expressions (ACCUMULATE-START-P wasn't set to NIL) + +Version 0.8.1 +2004-09-30 +Patches for Genera 8.5 (thanks to Patrick O'Donnell) + +Version 0.8.0 +2004-09-16 +Added parse tree synonyms (thanks to Patrick O'Donnell) + +Version 0.7.9 +2004-07-13 +Fixed bug in DO-SCANS (caught by Jan Rychter) + +Version 0.7.8 +2004-07-13 +New SIMPLE-CALLS keyword argument for REGEX-REPLACE(-ALL) +Added environment parameter to compiler macros (thanks to c.l.l article by Joe Marshall) +Added compiler macros for SCAN-TO-STRINGS and REGEX-REPLACE(-ALL) (they somehow got lost) + +Version 0.7.7 +2004-05-19 +Fixed bug in NEWLINE-SKIPPER (caught by RegexCoach user Thomas-Paz Hartman) +Added doc strings for PPCRE-SYNTAX-ERROR and friends (after playing with slime-apropos-package) +Added hyperdoc support + +Version 0.7.6 +2004-04-20 +The closures created by CREATE-BMH-MATCHER now cleanly cope with negative arguments (bug caught by Damien Kick) + +Version 0.7.5 +2004-04-19 +Fixed a bug with constant-length repetitions of . (dot) in single-line mode (caught by RegexCoach user Lee Gold) + +Version 0.7.4 +2004-02-16 +Fixed wrong call to SIGNAL-PPCRE-SIGNAL-ERROR in lexer.lisp (caught by Peter Graves) +Added :CL-PPCRE to *FEATURES* (for CL-INTERPOL) +Compiler macro for SPLIT + +Version 0.7.3 +2004-01-28 +Fixed bug in CURRENT-MIN-REST for lookaheads (reported by RegexCoach user Thomas-Paz Hartman) +Added tests for this bug + +Version 0.7.2 +2004-01-27 +Fixed typo (SUBSEQ/NSUBSEQ) in SPLIT (thanks to Alan Ruttenberg) +Updated docs with respect to ECL (thanks to Alex Mizrahi) +Mention FreeBSD port in docs + +Version 0.7.1 +2003-10-24 +Fixed version numbers in docs (thanks to Sébastien Saint-Sevin) + +Version 0.7.0 +2003-10-23 +New macros REGISTER-GROUPS-BIND and DO-REGISTER-GROUPS +Added SHAREP keyword argument to most API functions and macros +Mention CL-INTERPOL in docs +Partial code cleanup (using WITH-UNIQUE-NAMES and REBINDING) + +Version 0.6.1 +2003-10-11 +Added EXTERNAL-FORMAT keyword args to CL-PPCRE-TEST:TEST for some CLs (thanks to JP Massar and Scott D. Kalter) +Fixed bug with REGEX-REPLACE and REGEX-REPLACE-ALL when (= START END) was true +Added doc sections for quoting problems and backslash confusions (thanks to conversations with Peter Seibel) +Disable quoting in definition of QUOTE-SECTIONS so you can always safely rebuild CL-PPCRE + +Version 0.6.0 +2003-10-07 +CL-PPCRE now has its own condition types +Added support for Perl's \Q and \E (Peter Seibel convinced me to do it) - see QUOTE-META-CHARS and *ALLOW-QUOTING* +Added tests for this new feature +Threaded tests are more verbose now and use only keyword args + +Version 0.5.9 +2003-10-03 +Changed "^" optimizations with respect to constant end strings with offsets (bug caught by Yexuan Gui) +Added tests for this bug +Removed *.dos files from CL-PPCRE-TEST tests (thanks to JP Massar) +Added threaded tests for SBCL (thanks to Christophe Rhodes) + +Version 0.5.8 +2003-09-17 +Optimizations for ".*" were too optimistic when look-behinds were involved +Added tests for this bug +Removed *.dos files + +Version 0.5.7 +2003-08-20 +Fixed (CL-PPCRE:SCAN "(.)X$" "ABCX" :START 4) bug (spotted by Tibor Simko) +Forgot to export *REGEX-CHAR-CODE-LIMIT* in Corman version of DEFPACKAGE +Removed Emacs local variables from source code (finally...) +Mention Gentoo in docs + +Version 0.5.6 +2003-06-30 +Replaced wrong COPY-REGEX code for WORD-BOUNDARY objects (detected by Max Goldberg) +Added info about possible TRUENAME problems with ACL in README (thanks to Kevin Layer for providing a patch for this) + +Version 0.5.5 +2003-06-09 +Patch for SBCL/Debian compatibility by Kevin Rosenberg +Simpler version of compiler macro +Availability through asdf-install + +Version 0.5.4 +2003-04-09 +Added DESTRUCTIVE keyword to CREATE-SCANNER + +Version 0.5.3 +2003-03-31 +Fixed bug in REGEX-REPLACE (replacement string couldn't contain literal backslash) +Fixed bug in definition of CHAR-CLASS (since 0.5.0 the hash slot may be NIL - CMUCL's new PCL detects this) +Micro-optimization in INSERT-CHAR-CLASS-TESTER: CHAR-NOT-GREATERP instead of CHAR-DOWNCASE + +Version 0.5.2 +2003-03-28 +Better compiler macro (thanks to Kent M. Pitman) + +Version 0.5.1 +2003-03-27 +Removed compiler macro + +Version 0.5.0 +2003-03-27 +Lexer, parser, and converter mostly re-written to reduce consing and increase speed +Get rid of FIX-POS in lexer and parser, "ism" flags are handled after parsing now +Smaller test suite (again) due to literal embedding of line breaks +Seperate test files for DOS line endings +Replaced constant +REGEX-CHAR-CODE-LIMIT+ with special variable *REGEX-CHAR-CODE-LIMIT* + +Version 0.4.1 +2003-03-19 +Added compiler macro for SCAN +Changed test suite to be nicer to Corman Lisp and ECL (see docs for new syntax) +Incorporated visual feedback (dots) in test suite (thanks to JP Massar) +Added README file +Replaced STRING-LIST-TO-SIMPLE-STRING with a much improved version by JP Massar + +Version 0.4.0 +2003-02-27 +Added *USE-BMH-MATCHER* + +Version 0.3.2 +2003-02-21 +Added load.lisp +Various minor changes for Corman Lisp compatibility (thanks to Karsten Poeck and JP Massar) + +Version 0.3.1 +2003-01-18 +Bugfix in CREATE-SCANNER (didn't work if flags were given and arg was a parse-tree) + +Version 0.3.0 +2003-01-12 +Added new features to REGEX-REPLACE and REGEX-REPLACE-ALL + +Version 0.2.0 +2003-01-11 +Make SPLIT more Perl-compatible, including new keyword parameters + +Version 0.1.4 +2003-01-10 +Don't move "^" and "\A" while iterating with DO-SCANS +Added link to Debian package + +Version 0.1.3 +2002-12-25 +More usable MK:DEFSYSTEM files (courtesy of Hannu Koivisto) +Fixed typo in documentation + +Version 0.1.2 +2002-12-22 +Added version numbers for Debian packaging +Be friendly to case-sensitive ACL images (courtesy of Kevin Rosenberg and Douglas Crosher) +"Fixed" two cases where declarations came after docstrings (because of bugs in Corman Lisp and older CMUCL versions) +Added #-cormanlisp to hide (INCF (THE FIXNUM POS)) from Corman Lisp +Added file doc/benchmarks.2002-12-22.txt + +Version 0.1.1 +2002-12-21 +Added asdf system definitions by Marco Baringer +Small additions to documentation +Correct (Emacs) local variables list in closures.lisp and api.lisp +Added this CHANGELOG + +Version 0.1.0 +2002-12-20 +Initial release diff --git a/practicals/libraries/cl-ppcre-1.2.3/README b/practicals/libraries/cl-ppcre-1.2.3/README new file mode 100644 index 0000000..cc1ba38 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/README @@ -0,0 +1,59 @@ +Complete documentation for CL-PPCRE can be found in the 'doc' +directory. + +CL-PPCRE also supports Nikodemus Siivola's HYPERDOC, see + and +. + +1. Installation + +1.1. Probably the easiest way is + + (load "/path/to/cl-ppcre/load.lisp") + + This should compile and load CL-PPCRE on most Common Lisp + implementations. + +1.2. With MK:DEFSYSTEM you can make a symbolic link from + 'cl-ppcre.system' and 'cl-ppcre-test.system' to your central registry + (which by default is in '/usr/local/lisp/Registry/') and then issue + the command + + (mk:compile-system "cl-ppcre") + + Note that this relies on TRUENAME returning the original file a + symbolic link is pointing to. This will only work with AllegroCL + 6.2 if you've applied all patches with (SYS:UPDATE-ALLEGRO). + +1.3. You can also use ASDF instead of MK:DEFSYSTEM in a similar way + (use the .asd files instead of the .system files). + +2. Test + +CL-PPCRE comes with a test suite that can be used to check its +compatibility with Perl's regex syntax. See the documentation on how +to use this test suite for benchmarks and on how to write your own +tests. + +2.1. If you've used 'load.lisp' to load CL-PPCRE you already have the + test suite loaded and can start the default tests with + + (cl-ppcre-test:test) + +2.2. With MK:DEFSYSTEM you need to compile the 'cl-ppcre-test' system + as well before you can proceed as in 2.1. + +2.3. Same for ASDF. + +Depending on your machine and your CL implementation the default test +will take between a few seconds and a couple of minutes. (It will +print a dot for every tenth test case while it proceeds to give some +visual feedback.) It should exactly report three 'errors' (662, 790, +and 1439) which are explained in the documentation. + +MCL might report an error for the ninth test case which is also +explained in the docs. + +Genera notes (thanks to Patrick O'Donnell): Some more tests will fail +because characters like #\Return, #\Linefeed, or #\Tab have encodings +which differ from Perl's (and thus CL-PPCRE's) expectations. diff --git a/practicals/libraries/cl-ppcre-1.2.3/api.lisp b/practicals/libraries/cl-ppcre-1.2.3/api.lisp new file mode 100644 index 0000000..7d3fb1f --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/api.lisp @@ -0,0 +1,1330 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/api.lisp,v 1.53 2005/01/25 01:04:06 edi Exp $ + +;;; The external API for creating and using scanners. + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre) + +(defgeneric create-scanner (regex &key case-insensitive-mode + multi-line-mode + single-line-mode + extended-mode + destructive) + (:documentation "Accepts a regular expression - either as a +parse-tree or as a string - and returns a scan closure which will scan +strings for this regular expression. The \"mode\" keyboard arguments +are equivalent to the imsx modifiers in Perl. If DESTRUCTIVE is not +NIL the function is allowed to destructively modify its first argument +\(but only if it's a parse tree).")) + +#-:use-acl-regexp2-engine +(defmethod create-scanner ((regex-string string) &key case-insensitive-mode + multi-line-mode + single-line-mode + extended-mode + destructive) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (ignore destructive)) + ;; parse the string into a parse-tree and then call CREATE-SCANNER + ;; again + (let* ((*extended-mode-p* extended-mode) + (quoted-regex-string (if *allow-quoting* + (quote-sections (clean-comments regex-string extended-mode)) + regex-string)) + (*syntax-error-string* (copy-seq quoted-regex-string))) + ;; wrap the result with :GROUP to avoid infinite loops for + ;; constant strings + (create-scanner (cons :group (list (parse-string quoted-regex-string))) + :case-insensitive-mode case-insensitive-mode + :multi-line-mode multi-line-mode + :single-line-mode single-line-mode + :destructive t))) + +#-:use-acl-regexp2-engine +(defmethod create-scanner ((scanner function) &key case-insensitive-mode + multi-line-mode + single-line-mode + extended-mode + destructive) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (ignore destructive)) + (when (or case-insensitive-mode multi-line-mode single-line-mode extended-mode) + (signal-ppcre-invocation-error + "You can't use the keyword arguments to modify an existing scanner.")) + scanner) + +#-:use-acl-regexp2-engine +(defmethod create-scanner ((parse-tree t) &key case-insensitive-mode + multi-line-mode + single-line-mode + extended-mode + destructive) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (when extended-mode + (signal-ppcre-invocation-error + "Extended mode doesn't make sense in parse trees.")) + ;; convert parse-tree into internal representation REGEX and at the + ;; same time compute the number of registers and the constant string + ;; (or anchor) the regex starts with (if any) + (unless destructive + (setq parse-tree (copy-tree parse-tree))) + (let (flags) + (if single-line-mode + (push :single-line-mode-p flags)) + (if multi-line-mode + (push :multi-line-mode-p flags)) + (if case-insensitive-mode + (push :case-insensitive-p flags)) + (when flags + (setq parse-tree (list :group (cons :flags flags) parse-tree)))) + (let ((*syntax-error-string* nil)) + (multiple-value-bind (regex reg-num starts-with) + (convert parse-tree) + ;; simplify REGEX by flattening nested SEQ and ALTERNATION + ;; constructs and gathering STR objects + (let ((regex (gather-strings (flatten regex)))) + ;; set the MIN-REST slots of the REPETITION objects + (compute-min-rest regex 0) + ;; set the OFFSET slots of the STR objects + (compute-offsets regex 0) + (let* (end-string-offset + end-anchored-p + ;; compute the constant string the regex ends with (if + ;; any) and at the same time set the special variables + ;; END-STRING-OFFSET and END-ANCHORED-P + (end-string (end-string regex)) + ;; if we found a non-zero-length end-string we create an + ;; efficient search function for it + (end-string-test (and end-string + (plusp (len end-string)) + (if (= 1 (len end-string)) + (create-char-searcher + (schar (str end-string) 0) + (case-insensitive-p end-string)) + (create-bmh-matcher + (str end-string) + (case-insensitive-p end-string))))) + ;; initialize the counters for CREATE-MATCHER-AUX + (*rep-num* 0) + (*zero-length-num* 0) + ;; create the actual matcher function (which does all the + ;; work of matching the regular expression) corresponding + ;; to REGEX and at the same time set the special + ;; variables *REP-NUM* and *ZERO-LENGTH-NUM* + (match-fn (create-matcher-aux regex #'identity)) + ;; if the regex starts with a string we create an + ;; efficient search function for it + (start-string-test (and (typep starts-with 'str) + (plusp (len starts-with)) + (if (= 1 (len starts-with)) + (create-char-searcher + (schar (str starts-with) 0) + (case-insensitive-p starts-with)) + (create-bmh-matcher + (str starts-with) + (case-insensitive-p starts-with)))))) + (declare (special end-string-offset end-anchored-p end-string)) + ;; now create the scanner and return it + (create-scanner-aux match-fn + (regex-min-length regex) + (or (start-anchored-p regex) + ;; a dot in single-line-mode also + ;; implicitely anchors the regex at + ;; the start, i.e. if we can't match + ;; from the first position we won't + ;; match at all + (and (typep starts-with 'everything) + (single-line-p starts-with))) + starts-with + start-string-test + ;; only mark regex as end-anchored if we + ;; found a non-zero-length string before + ;; the anchor + (and end-string-test end-anchored-p) + end-string-test + (if end-string-test + (len end-string) + nil) + end-string-offset + *rep-num* + *zero-length-num* + reg-num)))))) + +#+:use-acl-regexp2-engine +(declaim (inline create-scanner)) + +#+:use-acl-regexp2-engine +(defmethod create-scanner ((scanner regexp::regular-expression) &key case-insensitive-mode + multi-line-mode + single-line-mode + extended-mode + destructive) + (declare (ignore destructive)) + (when (or case-insensitive-mode multi-line-mode single-line-mode extended-mode) + (signal-ppcre-invocation-error + "You can't use the keyword arguments to modify an existing scanner.")) + scanner) + +#+:use-acl-regexp2-engine +(defmethod create-scanner ((parse-tree t) &key case-insensitive-mode + multi-line-mode + single-line-mode + extended-mode + destructive) + (declare (ignore destructive)) + (excl:compile-re parse-tree + :case-fold case-insensitive-mode + :ignore-whitespace extended-mode + :multiple-lines multi-line-mode + :single-line single-line-mode + :return :index)) + +(defgeneric scan (regex target-string &key start end) + (:documentation "Searches TARGET-STRING from START to END and tries +to match REGEX. On success returns four values - the start of the +match, the end of the match, and two arrays denoting the beginnings +and ends of register matches. On failure returns NIL. REGEX can be a +string which will be parsed according to Perl syntax, a parse tree, or +a pre-compiled scanner created by CREATE-SCANNER. TARGET-STRING will +be coerced to a simple string if it isn't one already.")) + +#-:use-acl-regexp2-engine +(defmethod scan ((regex-string string) target-string + &key (start 0) + (end (length target-string))) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + ;; note that the scanners are optimized for simple strings so we + ;; have to coerce TARGET-STRING into one if it isn't already + (funcall (create-scanner regex-string) + (maybe-coerce-to-simple-string target-string) + start end)) + +#-:use-acl-regexp2-engine +(defmethod scan ((scanner function) target-string + &key (start 0) + (end (length target-string))) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (funcall scanner + (maybe-coerce-to-simple-string target-string) + start end)) + +#-:use-acl-regexp2-engine +(defmethod scan ((parse-tree t) target-string + &key (start 0) + (end (length target-string))) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (funcall (create-scanner parse-tree) + (maybe-coerce-to-simple-string target-string) + start end)) + +#+:use-acl-regexp2-engine +(declaim (inline scan)) + +#+:use-acl-regexp2-engine +(defmethod scan ((parse-tree t) target-string + &key (start 0) + (end (length target-string))) + (when (< end start) + (return-from scan nil)) + (let ((results (multiple-value-list (excl:match-re parse-tree target-string + :start start + :end end + :return :index)))) + (declare (dynamic-extent results)) + (cond ((null (first results)) nil) + (t (let* ((no-of-regs (- (length results) 2)) + (reg-starts (make-array no-of-regs + :element-type '(or null fixnum))) + (reg-ends (make-array no-of-regs + :element-type '(or null fixnum))) + (match (second results))) + (loop for (start . end) in (cddr results) + for i from 0 + do (setf (aref reg-starts i) start + (aref reg-ends i) end)) + (values (car match) (cdr match) reg-starts reg-ends)))))) + +(define-compiler-macro scan (&whole form &environment env regex target-string &rest rest) + "Make sure that constant forms are compiled into scanners at compile time." + (cond ((constantp regex env) + `(scan (load-time-value + (create-scanner ,regex)) + ,target-string ,@rest)) + (t form))) + +(defun scan-to-strings (regex target-string &key (start 0) + (end (length target-string)) + sharedp) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Like SCAN but returns substrings of TARGET-STRING instead of +positions, i.e. this function returns two values on success: the whole +match as a string plus an array of substrings (or NILs) corresponding +to the matched registers. If SHAREDP is true, the substrings may share +structure with TARGET-STRING." + (multiple-value-bind (match-start match-end reg-starts reg-ends) + (scan regex target-string :start start :end end) + (unless match-start + (return-from scan-to-strings nil)) + (let ((substr-fn (if sharedp #'nsubseq #'subseq))) + (values (funcall substr-fn + target-string match-start match-end) + (map 'vector + (lambda (reg-start reg-end) + (if reg-start + (funcall substr-fn + target-string reg-start reg-end) + nil)) + reg-starts + reg-ends))))) + +(define-compiler-macro scan-to-strings + (&whole form &environment env regex target-string &rest rest) + "Make sure that constant forms are compiled into scanners at compile time." + (cond ((constantp regex env) + `(scan-to-strings (load-time-value + (create-scanner ,regex)) + ,target-string ,@rest)) + (t form))) + +(defmacro register-groups-bind (var-list (regex target-string + &key start end sharedp) + &body body) + "Executes BODY with the variables in VAR-LIST bound to the +corresponding register groups after TARGET-STRING has been matched +against REGEX, i.e. each variable is either bound to a string or to +NIL. If there is no match, BODY is _not_ executed. For each element of +VAR-LIST which is NIL there's no binding to the corresponding register +group. The number of variables in VAR-LIST must not be greater than +the number of register groups. If SHAREDP is true, the substrings may +share structure with TARGET-STRING." + (with-rebinding (target-string) + (with-unique-names (match-start match-end reg-starts reg-ends + start-index substr-fn) + `(multiple-value-bind (,match-start ,match-end ,reg-starts ,reg-ends) + (scan ,regex ,target-string :start (or ,start 0) + :end (or ,end (length ,target-string))) + (declare (ignore ,match-end)) + (when ,match-start + (let* ,(cons + `(,substr-fn (if ,sharedp + #'nsubseq + #'subseq)) + (loop for (function var) in (normalize-var-list var-list) + for counter from 0 + when var + collect `(,var (let ((,start-index + (aref ,reg-starts ,counter))) + (if ,start-index + (funcall ,function + (funcall ,substr-fn + ,target-string + ,start-index + (aref ,reg-ends ,counter))) + nil))))) + ,@body)))))) + +(defmacro do-scans ((match-start match-end reg-starts reg-ends regex + target-string + &optional result-form + &key start end) + &body body + &environment env) + "Iterates over TARGET-STRING and tries to match REGEX as often as +possible evaluating BODY with MATCH-START, MATCH-END, REG-STARTS, and +REG-ENDS bound to the four return values of each match in turn. After +the last match, returns RESULT-FORM if provided or NIL otherwise. An +implicit block named NIL surrounds DO-SCANS; RETURN may be used to +terminate the loop immediately. If REGEX matches an empty string the +scan is continued one position behind this match. BODY may start with +declarations." + (with-rebinding (target-string) + (with-unique-names (%start %end %regex scanner loop-tag block-name) + (declare (ignorable %regex scanner)) + ;; the NIL BLOCK to enable exits via (RETURN ...) + `(block nil + (let* ((,%start (or ,start 0)) + (*real-start-pos* ,%start) + (,%end (or ,end (length ,target-string))) + ,@(unless (constantp regex env) + ;; leave constant regular expressions as they are - + ;; SCAN's compiler macro will take care of them; + ;; otherwise create a scanner unless the regex is + ;; already a function (otherwise SCAN will do this + ;; on each iteration) + `((,%regex ,regex) + (,scanner (typecase ,%regex + (function ,%regex) + (t (create-scanner ,%regex))))))) + ;; coerce TARGET-STRING to a simple string unless it is one + ;; already (otherwise SCAN will do this on each iteration) + (setq ,target-string + (maybe-coerce-to-simple-string ,target-string)) + ;; a named BLOCK so we can exit the TAGBODY + (block ,block-name + (tagbody + ,loop-tag + ;; invoke SCAN and bind the returned values to the + ;; provided variables + (multiple-value-bind + (,match-start ,match-end ,reg-starts ,reg-ends) + (scan ,(cond ((constantp regex env) regex) + (t scanner)) + ,target-string :start ,%start :end ,%end) + ;; declare the variables to be IGNORABLE to prevent the + ;; compiler from issuing warnings + (declare + (ignorable ,match-start ,match-end ,reg-starts ,reg-ends)) + (unless ,match-start + ;; stop iteration on first failure + (return-from ,block-name ,result-form)) + ;; execute BODY (wrapped in LOCALLY so it can start with + ;; declarations) + (locally + ,@body) + ;; advance by one position if we had a zero-length match + (setq ,%start (if (= ,match-start ,match-end) + (1+ ,match-end) + ,match-end))) + (go ,loop-tag)))))))) + +(defmacro do-matches ((match-start match-end regex + target-string + &optional result-form + &key start end) + &body body) + "Iterates over TARGET-STRING and tries to match REGEX as often as +possible evaluating BODY with MATCH-START and MATCH-END bound to the +start/end positions of each match in turn. After the last match, +returns RESULT-FORM if provided or NIL otherwise. An implicit block +named NIL surrounds DO-MATCHES; RETURN may be used to terminate the +loop immediately. If REGEX matches an empty string the scan is +continued one position behind this match. BODY may start with +declarations." + ;; this is a simplified form of DO-SCANS - we just provide two dummy + ;; vars and ignore them + (with-unique-names (reg-starts reg-ends) + `(do-scans (,match-start ,match-end + ,reg-starts ,reg-ends + ,regex ,target-string + ,result-form + :start ,start :end ,end) + ,@body))) + +(defmacro do-matches-as-strings ((match-var regex + target-string + &optional result-form + &key start end sharedp) + &body body) + "Iterates over TARGET-STRING and tries to match REGEX as often as +possible evaluating BODY with MATCH-VAR bound to the substring of +TARGET-STRING corresponding to each match in turn. After the last +match, returns RESULT-FORM if provided or NIL otherwise. An implicit +block named NIL surrounds DO-MATCHES-AS-STRINGS; RETURN may be used to +terminate the loop immediately. If REGEX matches an empty string the +scan is continued one position behind this match. If SHAREDP is true, +the substrings may share structure with TARGET-STRING. BODY may start +with declarations." + (with-rebinding (target-string) + (with-unique-names (match-start match-end substr-fn) + `(let ((,substr-fn (if ,sharedp #'nsubseq #'subseq))) + ;; simple use DO-MATCHES to extract the substrings + (do-matches (,match-start ,match-end ,regex ,target-string + ,result-form :start ,start :end ,end) + (let ((,match-var + (funcall ,substr-fn + ,target-string ,match-start ,match-end))) + ,@body)))))) + +(defmacro do-register-groups (var-list (regex target-string + &optional result-form + &key start end sharedp) + &body body) + "Iterates over TARGET-STRING and tries to match REGEX as often as +possible evaluating BODY with the variables in VAR-LIST bound to the +corresponding register groups for each match in turn, i.e. each +variable is either bound to a string or to NIL. For each element of +VAR-LIST which is NIL there's no binding to the corresponding register +group. The number of variables in VAR-LIST must not be greater than +the number of register groups. After the last match, returns +RESULT-FORM if provided or NIL otherwise. An implicit block named NIL +surrounds DO-REGISTER-GROUPS; RETURN may be used to terminate the loop +immediately. If REGEX matches an empty string the scan is continued +one position behind this match. If SHAREDP is true, the substrings may +share structure with TARGET-STRING. BODY may start with declarations." + (with-rebinding (target-string) + (with-unique-names (substr-fn match-start match-end + reg-starts reg-ends start-index) + `(let ((,substr-fn (if ,sharedp + #'nsubseq + #'subseq))) + (do-scans (,match-start ,match-end ,reg-starts ,reg-ends + ,regex ,target-string + ,result-form :start ,start :end ,end) + (let ,(loop for (function var) in (normalize-var-list var-list) + for counter from 0 + when var + collect `(,var (let ((,start-index + (aref ,reg-starts ,counter))) + (if ,start-index + (funcall ,function + (funcall ,substr-fn + ,target-string + ,start-index + (aref ,reg-ends ,counter))) + nil)))) + ,@body)))))) + +(defun all-matches (regex target-string + &key (start 0) + (end (length target-string))) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Returns a list containing the start and end positions of all +matches of REGEX against TARGET-STRING, i.e. if there are N matches +the list contains (* 2 N) elements. If REGEX matches an empty string +the scan is continued one position behind this match." + (let (result-list) + (do-matches (match-start match-end + regex target-string + (nreverse result-list) + :start start :end end) + (push match-start result-list) + (push match-end result-list)))) + +(define-compiler-macro all-matches (&whole form &environment env regex &rest rest) + "Make sure that constant forms are compiled into scanners at +compile time." + (cond ((constantp regex env) + `(all-matches (load-time-value + (create-scanner ,regex)) + ,@rest)) + (t form))) + +(defun all-matches-as-strings (regex target-string + &key (start 0) + (end (length target-string)) + sharedp) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Returns a list containing all substrings of TARGET-STRING which +match REGEX. If REGEX matches an empty string the scan is continued +one position behind this match. If SHAREDP is true, the substrings may +share structure with TARGET-STRING." + (let (result-list) + (do-matches-as-strings (match regex target-string (nreverse result-list) + :start start :end end :sharedp sharedp) + (push match result-list)))) + +(define-compiler-macro all-matches-as-strings (&whole form &environment env regex &rest rest) + "Make sure that constant forms are compiled into scanners at +compile time." + (cond ((constantp regex env) + `(all-matches-as-strings + (load-time-value + (create-scanner ,regex)) + ,@rest)) + (t form))) + +(defun split (regex target-string + &key (start 0) + (end (length target-string)) + limit + with-registers-p + omit-unmatched-p + sharedp) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Matches REGEX against TARGET-STRING as often as possible and +returns a list of the substrings between the matches. If +WITH-REGISTERS-P is true, substrings corresponding to matched +registers are inserted into the list as well. If OMIT-UNMATCHED-P is +true, unmatched registers will simply be left out, otherwise they will +show up as NIL. LIMIT limits the number of elements returned - +registers aren't counted. If LIMIT is NIL (or 0 which is equivalent), +trailing empty strings are removed from the result list. If REGEX +matches an empty string the scan is continued one position behind this +match. If SHAREDP is true, the substrings may share structure with +TARGET-STRING." + ;; initialize list of positions POS-LIST to extract substrings with + ;; START so that the start of the next match will mark the end of + ;; the first substring + (let ((pos-list (list start)) + (counter 0)) + ;; how would Larry Wall do it? + (when (eql limit 0) + (setq limit nil)) + (do-scans (match-start match-end + reg-starts reg-ends + regex target-string nil + :start start :end end) + (unless (and (= match-start match-end) + (= match-start (car pos-list))) + ;; push start of match on list unless this would be an empty + ;; string adjacent to the last element pushed onto the list + (when (and limit + (>= (incf counter) limit)) + (return)) + (push match-start pos-list) + (when with-registers-p + ;; optionally insert matched registers + (loop for reg-start across reg-starts + for reg-end across reg-ends + if reg-start + ;; but only if they've matched + do (push reg-start pos-list) + (push reg-end pos-list) + else unless omit-unmatched-p + ;; or if we're allowed to insert NIL instead + do (push nil pos-list) + (push nil pos-list))) + ;; now end of match + (push match-end pos-list))) + ;; end of whole string + (push end pos-list) + ;; now collect substrings + (nreverse + (loop with substr-fn = (if sharedp #'nsubseq #'subseq) + with string-seen = nil + for (this-end this-start) on pos-list by #'cddr + ;; skip empty strings from end of list + if (or limit + (setq string-seen + (or string-seen + (and this-start + (> this-end this-start))))) + collect (if this-start + (funcall substr-fn + target-string this-start this-end) + nil))))) + +(define-compiler-macro split (&whole form &environment env regex target-string &rest rest) + "Make sure that constant forms are compiled into scanners at compile time." + (cond ((constantp regex env) + `(split (load-time-value + (create-scanner ,regex)) + ,target-string ,@rest)) + (t form))) + +(defun string-case-modifier (str from to start end) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (type fixnum from to start end)) + "Checks whether all words in STR between FROM and TO are upcased, +downcased or capitalized and returns a function which applies a +corresponding case modification to strings. Returns #'IDENTITY +otherwise, especially if words in the target area extend beyond FROM +or TO. STR is supposed to be bounded by START and END. It is assumed +that (<= START FROM TO END)." + (case + (if (or (<= to from) + (and (< start from) + (alphanumericp (char str (1- from))) + (alphanumericp (char str from))) + (and (< to end) + (alphanumericp (char str to)) + (alphanumericp (char str (1- to))))) + ;; if it's a zero-length string or if words extend beyond FROM + ;; or TO we return NIL, i.e. #'IDENTITY + nil + ;; otherwise we loop through STR from FROM to TO + (loop with last-char-both-case + with current-result + for index of-type fixnum from from below to + for chr = (char str index) + do (cond ((not #-:cormanlisp (both-case-p chr) + #+:cormanlisp (or (upper-case-p chr) + (lower-case-p chr))) + ;; this character doesn't have a case so we + ;; consider it as a word boundary (note that + ;; this differs from how \b works in Perl) + (setq last-char-both-case nil)) + ((upper-case-p chr) + ;; an uppercase character + (setq current-result + (if last-char-both-case + ;; not the first character in a + (case current-result + ((:undecided) :upcase) + ((:downcase :capitalize) (return nil)) + ((:upcase) current-result)) + (case current-result + ((nil) :undecided) + ((:downcase) (return nil)) + ((:capitalize :upcase) current-result))) + last-char-both-case t)) + (t + ;; a lowercase character + (setq current-result + (case current-result + ((nil) :downcase) + ((:undecided) :capitalize) + ((:downcase) current-result) + ((:capitalize) (if last-char-both-case + current-result + (return nil))) + ((:upcase) (return nil))) + last-char-both-case t))) + finally (return current-result))) + ((nil) #'identity) + ((:undecided :upcase) #'string-upcase) + ((:downcase) #'string-downcase) + ((:capitalize) #'string-capitalize))) + +;; first create a scanner to identify the special parts of the +;; replacement string (eat your own dog food...) +#-:cormanlisp +(let* ((*use-bmh-matchers* nil) + (reg-scanner (create-scanner "\\\\(?:\\\\|\\{\\d+\\}|\\d+|&|`|')"))) + (defmethod build-replacement-template ((replacement-string string)) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Converts a replacement string for REGEX-REPLACE or +REGEX-REPLACE-ALL into a replacement template which is an +S-expression." + (let ((from 0) + ;; COLLECTOR will hold the (reversed) template + (collector '())) + ;; scan through all special parts of the replacement string + (do-matches (match-start match-end reg-scanner replacement-string) + (when (< from match-start) + ;; strings between matches are copied verbatim + (push (subseq replacement-string from match-start) collector)) + ;; PARSE-START is true if the pattern matched a number which + ;; refers to a register + (let* ((parse-start (position-if #'digit-char-p + replacement-string + :start match-start + :end match-end)) + (token (if parse-start + (1- (parse-integer replacement-string + :start parse-start + :junk-allowed t)) + ;; if we didn't match a number we convert the + ;; character to a symbol + (case (char replacement-string (1+ match-start)) + ((#\&) :match) + ((#\`) :before-match) + ((#\') :after-match) + ((#\\) :backslash))))) + (when (and (numberp token) (< token 0)) + ;; make sure we don't accept something like "\\0" + (signal-ppcre-invocation-error + "Illegal substring ~S in replacement string" + (subseq replacement-string match-start match-end))) + (push token collector)) + ;; remember where the match ended + (setq from match-end)) + (when (< from (length replacement-string)) + ;; push the rest of the replacement string onto the list + (push (subseq replacement-string from) collector)) + (nreverse collector)))) + +#-:cormanlisp +(defmethod build-replacement-template ((replacement-function function)) + (list replacement-function)) + +#-:cormanlisp +(defmethod build-replacement-template ((replacement-function-symbol symbol)) + (list replacement-function-symbol)) + +#-:cormanlisp +(defmethod build-replacement-template ((replacement-list list)) + replacement-list) + +;;; Corman Lisp's methods can't be closures... :( +#+:cormanlisp +(let* ((*use-bmh-matchers* nil) + (reg-scanner (create-scanner "\\\\(?:\\\\|\\{\\d+\\}|\\d+|&|`|')"))) + (defun build-replacement-template (replacement) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (typecase replacement + (string + (let ((from 0) + ;; COLLECTOR will hold the (reversed) template + (collector '())) + ;; scan through all special parts of the replacement string + (do-matches (match-start match-end reg-scanner replacement) + (when (< from match-start) + ;; strings between matches are copied verbatim + (push (subseq replacement from match-start) collector)) + ;; PARSE-START is true if the pattern matched a number which + ;; refers to a register + (let* ((parse-start (position-if #'digit-char-p + replacement + :start match-start + :end match-end)) + (token (if parse-start + (1- (parse-integer replacement + :start parse-start + :junk-allowed t)) + ;; if we didn't match a number we convert the + ;; character to a symbol + (case (char replacement (1+ match-start)) + ((#\&) :match) + ((#\`) :before-match) + ((#\') :after-match) + ((#\\) :backslash))))) + (when (and (numberp token) (< token 0)) + ;; make sure we don't accept something like "\\0" + (signal-ppcre-invocation-error + "Illegal substring ~S in replacement string" + (subseq replacement match-start match-end))) + (push token collector)) + ;; remember where the match ended + (setq from match-end)) + (when (< from (length replacement)) + ;; push the rest of the replacement string onto the list + (push (nsubseq replacement from) collector)) + (nreverse collector))) + (list + replacement) + (t + (list replacement))))) + +(defun build-replacement (replacement-template + target-string + start end + match-start match-end + reg-starts reg-ends + simple-calls) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Accepts a replacement template and the current values from the +matching process in REGEX-REPLACE or REGEX-REPLACE-ALL and returns the +corresponding template." + ;; the upper exclusive bound of the register numbers in the regular + ;; expression + (let ((reg-bound (if reg-starts + (array-dimension reg-starts 0) + 0))) + (with-output-to-string (s) + (loop for token in replacement-template + do (typecase token + (string + ;; transfer string parts verbatim + (write-string token s)) + (integer + ;; replace numbers with the corresponding registers + (when (>= token reg-bound) + ;; but only if the register was referenced in the + ;; regular expression + (signal-ppcre-invocation-error + "Reference to non-existent register ~A in replacement string" + (1+ token))) + (when (svref reg-starts token) + ;; and only if it matched, i.e. no match results + ;; in an empty string + (write-string target-string s + :start (svref reg-starts token) + :end (svref reg-ends token)))) + (function + (write-string + (cond (simple-calls + (apply token + (nsubseq target-string match-start match-end) + (map 'list + (lambda (reg-start reg-end) + (and reg-start + (nsubseq target-string reg-start reg-end))) + reg-starts reg-ends))) + (t + (funcall token + target-string + start end + match-start match-end + reg-starts reg-ends))) + s)) + (symbol + (case token + ((:backslash) + ;; just a backslash + (write-char #\\ s)) + ((:match) + ;; the whole match + (write-string target-string s + :start match-start + :end match-end)) + ((:before-match) + ;; the part of the target string before the match + (write-string target-string s + :start start + :end match-start)) + ((:after-match) + ;; the part of the target string after the match + (write-string target-string s + :start match-end + :end end)) + (otherwise + (write-string + (cond (simple-calls + (apply token + (nsubseq target-string match-start match-end) + (map 'list + (lambda (reg-start reg-end) + (and reg-start + (nsubseq target-string reg-start reg-end))) + reg-starts reg-ends))) + (t + (funcall token + target-string + start end + match-start match-end + reg-starts reg-ends))) + s))))))))) + +(defun replace-aux (target-string replacement pos-list reg-list + start end preserve-case simple-calls) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Auxiliary function used by REGEX-REPLACE and +REGEX-REPLACE-ALL. POS-LIST contains a list with the start and end +positions of all matches while REG-LIST contains a list of arrays +representing the corresponding register start and end positions." + ;; build the template once before we start the loop + (let ((replacement-template (build-replacement-template replacement))) + (with-output-to-string (s) + ;; loop through all matches and take the start and end of the + ;; whole string into account + (loop for (from to) on (append (list start) pos-list (list end)) + ;; alternate between replacement and no replacement + for replace = nil then (and (not replace) to) + for reg-starts = (if replace (pop reg-list) nil) + for reg-ends = (if replace (pop reg-list) nil) + for curr-replacement = (if replace + ;; build the replacement string + (build-replacement replacement-template + target-string + start end + from to + reg-starts reg-ends + simple-calls) + nil) + while to + if replace + do (write-string (if preserve-case + ;; modify the case of the replacement + ;; string if necessary + (funcall (string-case-modifier target-string + from to + start end) + curr-replacement) + curr-replacement) + s) + else + ;; no replacement + do (write-string target-string s :start from :end to))))) + +(defun regex-replace (regex target-string replacement + &key (start 0) + (end (length target-string)) + preserve-case + simple-calls) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Try to match TARGET-STRING between START and END against REGEX and +replace the first match with REPLACEMENT. + + REPLACEMENT can be a string which may contain the special substrings +\"\\&\" for the whole match, \"\\`\" for the part of TARGET-STRING +before the match, \"\\'\" for the part of TARGET-STRING after the +match, \"\\N\" or \"\\{N}\" for the Nth register where N is a positive +integer. + + REPLACEMENT can also be a function designator in which case the +match will be replaced with the result of calling the function +designated by REPLACEMENT with the arguments TARGET-STRING, START, +END, MATCH-START, MATCH-END, REG-STARTS, and REG-ENDS. (REG-STARTS and +REG-ENDS are arrays holding the start and end positions of matched +registers or NIL - the meaning of the other arguments should be +obvious.) + + Finally, REPLACEMENT can be a list where each element is a string, +one of the symbols :MATCH, :BEFORE-MATCH, or :AFTER-MATCH - +corresponding to \"\\&\", \"\\`\", and \"\\'\" above -, an integer N - +representing register (1+ N) -, or a function designator. + + If PRESERVE-CASE is true, the replacement will try to preserve the +case (all upper case, all lower case, or capitalized) of the +match. The result will always be a fresh string, even if REGEX doesn't +match." + (multiple-value-bind (match-start match-end reg-starts reg-ends) + (scan regex target-string :start start :end end) + (if match-start + (replace-aux target-string replacement + (list match-start match-end) + (list reg-starts reg-ends) + start end preserve-case simple-calls) + (subseq target-string start end)))) + +(define-compiler-macro regex-replace + (&whole form &environment env regex target-string replacement &rest rest) + "Make sure that constant forms are compiled into scanners at compile time." + (cond ((constantp regex env) + `(regex-replace (load-time-value + (create-scanner ,regex)) + ,target-string ,replacement ,@rest)) + (t form))) + +(defun regex-replace-all (regex target-string replacement + &key (start 0) + (end (length target-string)) + preserve-case + simple-calls) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Try to match TARGET-STRING between START and END against REGEX and +replace all matches with REPLACEMENT. + + REPLACEMENT can be a string which may contain the special substrings +\"\\&\" for the whole match, \"\\`\" for the part of TARGET-STRING +before the match, \"\\'\" for the part of TARGET-STRING after the +match, \"\\N\" or \"\\{N}\" for the Nth register where N is a positive +integer. + + REPLACEMENT can also be a function designator in which case the +match will be replaced with the result of calling the function +designated by REPLACEMENT with the arguments TARGET-STRING, START, +END, MATCH-START, MATCH-END, REG-STARTS, and REG-ENDS. (REG-STARTS and +REG-ENDS are arrays holding the start and end positions of matched +registers or NIL - the meaning of the other arguments should be +obvious.) + + Finally, REPLACEMENT can be a list where each element is a string, +one of the symbols :MATCH, :BEFORE-MATCH, or :AFTER-MATCH - +corresponding to \"\\&\", \"\\`\", and \"\\'\" above -, an integer N - +representing register (1+ N) -, or a function designator. + + If PRESERVE-CASE is true, the replacement will try to preserve the +case (all upper case, all lower case, or capitalized) of the +match. The result will always be a fresh string, even if REGEX doesn't +match." + (let ((pos-list '()) + (reg-list '())) + (do-scans (match-start match-end reg-starts reg-ends regex target-string + nil + :start start :end end) + (push match-start pos-list) + (push match-end pos-list) + (push reg-starts reg-list) + (push reg-ends reg-list)) + (if pos-list + (replace-aux target-string replacement + (nreverse pos-list) + (nreverse reg-list) + start end preserve-case simple-calls) + (subseq target-string start end)))) + +(define-compiler-macro regex-replace-all + (&whole form &environment env regex target-string replacement &rest rest) + "Make sure that constant forms are compiled into scanners at compile time." + (cond ((constantp regex env) + `(regex-replace-all (load-time-value + (create-scanner ,regex)) + ,target-string ,replacement ,@rest)) + (t form))) + +#-:cormanlisp +(defmacro regex-apropos-aux ((regex packages case-insensitive &optional return-form) + &body body) + "Auxiliary macro used by REGEX-APROPOS and REGEX-APROPOS-LIST. Loops +through PACKAGES and executes BODY with SYMBOL bound to each symbol +which matches REGEX. Optionally evaluates and returns RETURN-FORM at +the end. If CASE-INSENSITIVE is true and REGEX isn't already a +scanner, a case-insensitive scanner is used." + (with-rebinding (regex) + (with-unique-names (scanner %packages next morep) + `(let* ((,scanner (create-scanner ,regex + :case-insensitive-mode + (and ,case-insensitive + (not (functionp ,regex))))) + (,%packages (or ,packages + (list-all-packages)))) + (with-package-iterator (,next ,%packages :external :internal) + (loop + (multiple-value-bind (,morep symbol) + (,next) + (unless ,morep + (return ,return-form)) + (when (scan ,scanner (symbol-name symbol)) + ,@body)))))))) + +;;; The following two functions were provided by Karsten Poeck + +#+:cormanlisp +(defmacro do-with-all-symbols ((variable package-packagelist) &body body) + (with-unique-names (pack-var iter-sym) + `(if (listp ,package-packagelist) + (dolist (,pack-var ,package-packagelist) + (do-symbols (,iter-sym ,pack-var) + ,@body)) + (do-symbols (,iter-sym ,package-packagelist) + ,@body)))) + +#+:cormanlisp +(defmacro regex-apropos-aux ((regex packages case-insensitive &optional return-form) + &body body) + "Auxiliary macro used by REGEX-APROPOS and REGEX-APROPOS-LIST. Loops +through PACKAGES and executes BODY with SYMBOL bound to each symbol +which matches REGEX. Optionally evaluates and returns RETURN-FORM at +the end. If CASE-INSENSITIVE is true and REGEX isn't already a +scanner, a case-insensitive scanner is used." + (with-rebinding (regex) + (with-unique-names (scanner %packages) + `(let* ((,scanner (create-scanner ,regex + :case-insensitive-mode + (and ,case-insensitive + (not (functionp ,regex))))) + (,%packages (or ,packages + (list-all-packages)))) + (do-with-all-symbols (symbol ,%packages) + (when (scan ,scanner (symbol-name symbol)) + ,@body)) + ,return-form)))) + +(defun regex-apropos-list (regex &optional packages &key (case-insensitive t)) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Similar to the standard function APROPOS-LIST but returns a list of +all symbols which match the regular expression REGEX. If +CASE-INSENSITIVE is true and REGEX isn't already a scanner, a +case-insensitive scanner is used." + (let ((collector '())) + (regex-apropos-aux (regex packages case-insensitive collector) + (push symbol collector)))) + +(defun print-symbol-info (symbol) + "Auxiliary function used by REGEX-APROPOS. Tries to print some +meaningful information about a symbol." + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (handler-case + (let ((output-list '())) + (cond ((special-operator-p symbol) + (push "[special operator]" output-list)) + ((macro-function symbol) + (push "[macro]" output-list)) + ((fboundp symbol) + (let* ((function (symbol-function symbol)) + (compiledp (compiled-function-p function))) + (multiple-value-bind (lambda-expr closurep) + (function-lambda-expression function) + (push + (format nil + "[~:[~;compiled ~]~:[function~;closure~]]~:[~; ~A~]" + compiledp closurep lambda-expr (cadr lambda-expr)) + output-list))))) + (let ((class (find-class symbol nil))) + (when class + (push (format nil "[class] ~S" class) output-list))) + (cond ((keywordp symbol) + (push "[keyword]" output-list)) + ((constantp symbol) + (push (format nil "[constant]~:[~; value: ~S~]" + (boundp symbol) (symbol-value symbol)) output-list)) + ((boundp symbol) + (push #+(or LispWorks CLISP) "[variable]" + #-(or LispWorks CLISP) (format nil "[variable] value: ~S" + (symbol-value symbol)) + output-list))) + #-(or :cormanlisp :clisp) + (format t "~&~S ~<~;~^~A~@{~:@_~A~}~;~:>" symbol output-list) + #+(or :cormanlisp :clisp) + (loop for line in output-list + do (format t "~&~S ~A" symbol line))) + (condition () + ;; this seems to be necessary due to some errors I encountered + ;; with LispWorks + (format t "~&~S [an error occured while trying to print more info]" symbol)))) + +(defun regex-apropos (regex &optional packages &key (case-insensitive t)) + "Similar to the standard function APROPOS but returns a list of all +symbols which match the regular expression REGEX. If CASE-INSENSITIVE +is true and REGEX isn't already a scanner, a case-insensitive scanner +is used." + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (regex-apropos-aux (regex packages case-insensitive) + (print-symbol-info symbol)) + (values)) + +(let* ((*use-bmh-matchers* nil) + (non-word-char-scanner (create-scanner "[^a-zA-Z_0-9]"))) + (defun quote-meta-chars (string &key (start 0) (end (length string))) + "Quote, i.e. prefix with #\\\\, all non-word characters in STRING." + (regex-replace-all non-word-char-scanner string "\\\\\\&" + :start start :end end))) + +(let* ((*use-bmh-matchers* nil) + (*allow-quoting* nil) + (quote-char-scanner (create-scanner "\\\\Q")) + (section-scanner (create-scanner "\\\\Q((?:[^\\\\]|\\\\(?!Q))*?)(?:\\\\E|$)"))) + (defun quote-sections (string) + "Replace sections inside of STRING which are enclosed by \\Q and +\\E with the quoted equivalent of these sections \(see +QUOTE-META-CHARS). Repeat this as long as there are such +sections. These sections may nest." + (flet ((quote-substring (target-string start end match-start + match-end reg-starts reg-ends) + (declare (ignore start end match-start match-end)) + (quote-meta-chars target-string + :start (svref reg-starts 0) + :end (svref reg-ends 0)))) + (loop for result = string then (regex-replace-all section-scanner + result + #'quote-substring) + while (scan quote-char-scanner result) + finally (return result))))) + +(let* ((*use-bmh-matchers* nil) + (comment-scanner (create-scanner "(?s)\\(\\?#.*?\\)")) + (extended-comment-scanner (create-scanner "(?m:#.*?$)|(?s:\\(\\?#.*?\\))")) + (quote-token-scanner "\\\\[QE]") + (quote-token-replace-scanner "\\\\([QE])")) + (defun clean-comments (string &optional extended-mode) + "Clean \(?#...) comments within STRING for quoting, i.e. convert +\\Q to Q and \\E to E. If EXTENDED-MODE is true, also clean +end-of-line comments, i.e. those starting with #\\# and ending with +#\\Newline." + (flet ((remove-tokens (target-string start end match-start + match-end reg-starts reg-ends) + (declare (ignore start end reg-starts reg-ends)) + (loop for result = (nsubseq target-string match-start match-end) + then (regex-replace-all quote-token-replace-scanner result "\\1") + ;; we must probably repeat this because the comment + ;; can contain substrings like \\Q + while (scan quote-token-scanner result) + finally (return result)))) + (regex-replace-all (if extended-mode + extended-comment-scanner + comment-scanner) + string + #'remove-tokens)))) + +(defun parse-tree-synonym (symbol) + "Returns the parse tree the SYMBOL symbol is a synonym for. Returns +NIL is SYMBOL wasn't yet defined to be a synonym." + (get symbol 'parse-tree-synonym)) + +(defun (setf parse-tree-synonym) (new-parse-tree symbol) + "Defines SYMBOL to be a synonm for the parse tree NEW-PARSE-TREE." + (setf (get symbol 'parse-tree-synonym) new-parse-tree)) + +(defmacro define-parse-tree-synonym (name parse-tree) + "Defines the symbol NAME to be a synonym for the parse tree +PARSE-TREE. Both arguments are quoted." + `(eval-when (:compile-toplevel :load-toplevel :execute) + (setf (parse-tree-synonym ',name) ',parse-tree))) diff --git a/practicals/libraries/cl-ppcre-1.2.3/cl-ppcre-test.asd b/practicals/libraries/cl-ppcre-1.2.3/cl-ppcre-test.asd new file mode 100644 index 0000000..a050738 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/cl-ppcre-test.asd @@ -0,0 +1,40 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/cl-ppcre-test.asd,v 1.6 2004/04/20 11:37:35 edi Exp $ + +;;; This ASDF system definition was kindly provided by Marco Baringer. + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(defpackage #:cl-ppcre-test.system + (:use #:cl + #:asdf)) + +(in-package #:cl-ppcre-test.system) + +(defsystem #:cl-ppcre-test + :depends-on (#:cl-ppcre) + :components ((:file "ppcre-tests"))) diff --git a/practicals/libraries/cl-ppcre-1.2.3/cl-ppcre-test.system b/practicals/libraries/cl-ppcre-1.2.3/cl-ppcre-test.system new file mode 100644 index 0000000..41e5b17 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/cl-ppcre-test.system @@ -0,0 +1,40 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/cl-ppcre-test.system,v 1.8 2004/04/20 11:37:35 edi Exp $ + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-user) + +(defparameter *cl-ppcre-test-base-directory* + (make-pathname :name nil :type nil :version nil + :defaults (parse-namestring *load-truename*))) + +(mk:defsystem #:cl-ppcre-test + :source-pathname *cl-ppcre-test-base-directory* + :source-extension "lisp" + :depends-on (#:cl-ppcre) + :components ((:file "ppcre-tests"))) diff --git a/practicals/libraries/cl-ppcre-1.2.3/cl-ppcre.asd b/practicals/libraries/cl-ppcre-1.2.3/cl-ppcre.asd new file mode 100644 index 0000000..8025be5 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/cl-ppcre.asd @@ -0,0 +1,60 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/cl-ppcre.asd,v 1.9 2005/01/24 14:06:38 edi Exp $ + +;;; This ASDF system definition was kindly provided by Marco Baringer. + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(defpackage #:cl-ppcre.system + (:use #:cl + #:asdf)) + +(in-package #:cl-ppcre.system) + +(defsystem #:cl-ppcre + :serial t + :components ((:file "packages") + (:file "specials") + (:file "util") + (:file "errors") + #-:use-acl-regexp2-engine + (:file "lexer") + #-:use-acl-regexp2-engine + (:file "parser") + #-:use-acl-regexp2-engine + (:file "regex-class") + #-:use-acl-regexp2-engine + (:file "convert") + #-:use-acl-regexp2-engine + (:file "optimize") + #-:use-acl-regexp2-engine + (:file "closures") + #-:use-acl-regexp2-engine + (:file "repetition-closures") + #-:use-acl-regexp2-engine + (:file "scanner") + (:file "api"))) diff --git a/practicals/libraries/cl-ppcre-1.2.3/cl-ppcre.system b/practicals/libraries/cl-ppcre-1.2.3/cl-ppcre.system new file mode 100644 index 0000000..61d7d92 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/cl-ppcre.system @@ -0,0 +1,59 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/cl-ppcre.system,v 1.10 2005/01/24 20:22:27 edi Exp $ + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-user) + +(defparameter *cl-ppcre-base-directory* + (make-pathname :name nil :type nil :version nil + :defaults (parse-namestring *load-truename*))) + +(mk:defsystem #:cl-ppcre + :source-pathname *cl-ppcre-base-directory* + :source-extension "lisp" + :components ((:file "packages") + (:file "specials" :depends-on ("packages")) + (:file "util" :depends-on ("packages")) + (:file "errors" :depends-on ("util")) + #-:use-acl-regexp2-engine + (:file "lexer" :depends-on ("errors" "specials")) + #-:use-acl-regexp2-engine + (:file "parser" :depends-on ("lexer")) + #-:use-acl-regexp2-engine + (:file "regex-class" :depends-on ("parser")) + #-:use-acl-regexp2-engine + (:file "convert" :depends-on ("regex-class")) + #-:use-acl-regexp2-engine + (:file "optimize" :depends-on ("convert")) + #-:use-acl-regexp2-engine + (:file "closures" :depends-on ("optimize" "specials")) + #-:use-acl-regexp2-engine + (:file "repetition-closures" :depends-on ("closures")) + #-:use-acl-regexp2-engine + (:file "scanner" :depends-on ("repetition-closures")) + (:file "api" :depends-on ("scanner")))) diff --git a/practicals/libraries/cl-ppcre-1.2.3/closures.lisp b/practicals/libraries/cl-ppcre-1.2.3/closures.lisp new file mode 100644 index 0000000..37284c0 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/closures.lisp @@ -0,0 +1,583 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/closures.lisp,v 1.25 2004/10/14 12:40:39 edi Exp $ + +;;; Here we create the closures which together build the final +;;; scanner. + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre) + +(declaim (inline *string*= *string*-equal)) + +(defun *string*= (string2 start1 end1 start2 end2) + "Like STRING=, i.e. compares the special string *STRING* from START1 +to END1 with STRING2 from START2 to END2. Note that there's no +boundary check - this has to be implemented by the caller." + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (type fixnum start1 end1 start2 end2)) + (loop for string1-idx of-type fixnum from start1 below end1 + for string2-idx of-type fixnum from start2 below end2 + always (char= (schar *string* string1-idx) + (schar string2 string2-idx)))) + +(defun *string*-equal (string2 start1 end1 start2 end2) + "Like STRING-EQUAL, i.e. compares the special string *STRING* from +START1 to END1 with STRING2 from START2 to END2. Note that there's no +boundary check - this has to be implemented by the caller." + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (type fixnum start1 end1 start2 end2)) + (loop for string1-idx of-type fixnum from start1 below end1 + for string2-idx of-type fixnum from start2 below end2 + always (char-equal (schar *string* string1-idx) + (schar string2 string2-idx)))) + +(defgeneric create-matcher-aux (regex next-fn) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Creates a closure which takes one parameter, +START-POS, and tests whether REGEX can match *STRING* at START-POS +such that the call to NEXT-FN after the match would succeed.")) + +(defmethod create-matcher-aux ((seq seq) next-fn) + ;; the closure for a SEQ is a chain of closures for the elements of + ;; this sequence which call each other in turn; the last closure + ;; calls NEXT-FN + (loop for element in (reverse (elements seq)) + for curr-matcher = next-fn then next-matcher + for next-matcher = (create-matcher-aux element curr-matcher) + finally (return next-matcher))) + +(defmethod create-matcher-aux ((alternation alternation) next-fn) + ;; first create closures for all alternations of ALTERNATION + (let ((all-matchers (mapcar #'(lambda (choice) + (create-matcher-aux choice next-fn)) + (choices alternation)))) + ;; now create a closure which checks if one of the closures + ;; created above can succeed + (lambda (start-pos) + (declare (type fixnum start-pos)) + (loop for matcher in all-matchers + thereis (funcall (the function matcher) start-pos))))) + +(defmethod create-matcher-aux ((register register) next-fn) + ;; the position of this REGISTER within the whole regex; we start to + ;; count at 0 + (let ((num (num register))) + (declare (type fixnum num)) + ;; STORE-END-OF-REG is a thin wrapper around NEXT-FN which will + ;; update the corresponding values of *REGS-START* and *REGS-END* + ;; after the inner matcher has succeeded + (flet ((store-end-of-reg (start-pos) + (declare (type fixnum start-pos) + (type function next-fn)) + (setf (svref *reg-starts* num) (svref *regs-maybe-start* num) + (svref *reg-ends* num) start-pos) + (funcall next-fn start-pos))) + ;; the inner matcher is a closure corresponding to the regex + ;; wrapped by this REGISTER + (let ((inner-matcher (create-matcher-aux (regex register) + #'store-end-of-reg))) + (declare (type function inner-matcher)) + ;; here comes the actual closure for REGISTER + (lambda (start-pos) + (declare (type fixnum start-pos)) + ;; remember the old values of *REGS-START* and friends in + ;; case we cannot match + (let ((old-*reg-starts* (svref *reg-starts* num)) + (old-*regs-maybe-start* (svref *regs-maybe-start* num)) + (old-*reg-ends* (svref *reg-ends* num))) + ;; we cannot use *REGS-START* here because Perl allows + ;; regular expressions like /(a|\1x)*/ + (setf (svref *regs-maybe-start* num) start-pos) + (let ((next-pos (funcall inner-matcher start-pos))) + (unless next-pos + ;; restore old values on failure + (setf (svref *reg-starts* num) old-*reg-starts* + (svref *regs-maybe-start* num) old-*regs-maybe-start* + (svref *reg-ends* num) old-*reg-ends*)) + next-pos))))))) + +(defmethod create-matcher-aux ((lookahead lookahead) next-fn) + ;; create a closure which just checks for the inner regex and + ;; doesn't care about NEXT-FN + (let ((test-matcher (create-matcher-aux (regex lookahead) #'identity))) + (declare (type function next-fn test-matcher)) + (if (positivep lookahead) + ;; positive look-ahead: check success of inner regex, then call + ;; NEXT-FN + (lambda (start-pos) + (and (funcall test-matcher start-pos) + (funcall next-fn start-pos))) + ;; negative look-ahead: check failure of inner regex, then call + ;; NEXT-FN + (lambda (start-pos) + (and (not (funcall test-matcher start-pos)) + (funcall next-fn start-pos)))))) + +(defmethod create-matcher-aux ((lookbehind lookbehind) next-fn) + (let ((len (len lookbehind)) + ;; create a closure which just checks for the inner regex and + ;; doesn't care about NEXT-FN + (test-matcher (create-matcher-aux (regex lookbehind) #'identity))) + (declare (type function next-fn test-matcher) + (type fixnum len)) + (if (positivep lookbehind) + ;; positive look-behind: check success of inner regex (if we're + ;; far enough from the start of *STRING*), then call NEXT-FN + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (>= (- start-pos *start-pos*) len) + (funcall test-matcher (- start-pos len)) + (funcall next-fn start-pos))) + ;; negative look-behind: check failure of inner regex (if we're + ;; far enough from the start of *STRING*), then call NEXT-FN + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (or (< start-pos len) + (not (funcall test-matcher (- start-pos len)))) + (funcall next-fn start-pos)))))) + +(defmacro insert-char-class-tester ((char-class chr-expr) &body body) + "Utility macro to replace each occurence of '(CHAR-CLASS-TEST) +within BODY with the correct test (corresponding to CHAR-CLASS) +against CHR-EXPR." + (with-unique-names (%char-class) + ;; the actual substitution is done here: replace + ;; '(CHAR-CLASS-TEST) with NEW + (flet ((substitute-char-class-tester (new) + (subst new '(char-class-test) body + :test #'equalp))) + `(let* ((,%char-class ,char-class) + (hash (hash ,%char-class)) + (count (if hash + (hash-table-count hash) + most-positive-fixnum)) + ;; collect a list of "all" characters in the hash if + ;; there aren't more than two + (key-list (if (<= count 2) + (loop for chr being the hash-keys of hash + collect chr) + nil)) + downcasedp) + (declare (type fixnum count)) + ;; check if we can partition the hash into three ranges (or + ;; less) + (multiple-value-bind (min1 max1 min2 max2 min3 max3) + (create-ranges-from-hash hash) + ;; if that didn't work and CHAR-CLASS is case-insensitive we + ;; try it again with every character downcased + (when (and (not min1) + (case-insensitive-p ,%char-class)) + (multiple-value-setq (min1 max1 min2 max2 min3 max3) + (create-ranges-from-hash hash :downcasep t)) + (setq downcasedp t)) + (cond ((= count 1) + ;; hash contains exactly one character so we just + ;; check for this single character; (note that this + ;; actually can't happen because this case is + ;; optimized away in CONVERT already...) + (let ((chr1 (first key-list))) + ,@(substitute-char-class-tester + `(char= ,chr-expr chr1)))) + ((= count 2) + ;; hash contains exactly two characters + (let ((chr1 (first key-list)) + (chr2 (second key-list))) + ,@(substitute-char-class-tester + `(let ((chr ,chr-expr)) + (or (char= chr chr1) + (char= chr chr2)))))) + ((word-char-class-p ,%char-class) + ;; special-case: hash is \w, \W, [\w], [\W] or + ;; something equivalent + ,@(substitute-char-class-tester + `(word-char-p ,chr-expr))) + ((= count *regex-char-code-limit*) + ;; according to the ANSI standard we might have all + ;; possible characters in the hash even if it + ;; doesn't contain CHAR-CODE-LIMIT characters but + ;; this doesn't seem to be the case for current + ;; implementations (also note that this optimization + ;; implies that you must not have characters with + ;; character codes beyond *REGEX-CHAR-CODE-LIMIT* in + ;; your regexes if you've changed this limit); we + ;; expect the compiler to optimize this T "test" + ;; away + ,@(substitute-char-class-tester t)) + ((and downcasedp min1 min2 min3) + ;; three different ranges, downcased + ,@(substitute-char-class-tester + `(let ((chr ,chr-expr)) + (or (char-not-greaterp min1 chr max1) + (char-not-greaterp min2 chr max2) + (char-not-greaterp min3 chr max3))))) + ((and downcasedp min1 min2) + ;; two ranges, downcased + ,@(substitute-char-class-tester + `(let ((chr ,chr-expr)) + (or (char-not-greaterp min1 chr max1) + (char-not-greaterp min2 chr max2))))) + ((and downcasedp min1) + ;; one downcased range + ,@(substitute-char-class-tester + `(char-not-greaterp min1 ,chr-expr max1))) + ((and min1 min2 min3) + ;; three ranges + ,@(substitute-char-class-tester + `(let ((chr ,chr-expr)) + (or (char<= min1 chr max1) + (char<= min2 chr max2) + (char<= min3 chr max3))))) + ((and min1 min2) + ;; two ranges + ,@(substitute-char-class-tester + `(let ((chr ,chr-expr)) + (or (char<= min1 chr max1) + (char<= min2 chr max2))))) + (min1 + ;; one range + ,@(substitute-char-class-tester + `(char<= min1 ,chr-expr max1))) + (t + ;; the general case; note that most of the above + ;; "optimizations" are based on experiences and + ;; benchmarks with CMUCL - if you're really + ;; concerned with speed you might find out that the + ;; general case is almost always the best one for + ;; other implementations (because the speed of their + ;; hash-table access in relation to other operations + ;; might be better than in CMUCL) + ,@(substitute-char-class-tester + `(gethash ,chr-expr hash))))))))) + +(defmethod create-matcher-aux ((char-class char-class) next-fn) + (declare (type function next-fn)) + ;; insert a test against the current character within *STRING* + (insert-char-class-tester (char-class (schar *string* start-pos)) + (if (invertedp char-class) + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (< start-pos *end-pos*) + (not (char-class-test)) + (funcall next-fn (1+ start-pos)))) + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (< start-pos *end-pos*) + (char-class-test) + (funcall next-fn (1+ start-pos))))))) + +(defmethod create-matcher-aux ((str str) next-fn) + (declare (type fixnum *end-string-pos*) + (type function next-fn) + ;; this special value is set by CREATE-SCANNER when the + ;; closures are built + (special end-string)) + (let* ((len (len str)) + (case-insensitive-p (case-insensitive-p str)) + (start-of-end-string-p (start-of-end-string-p str)) + (skip (skip str)) + (str (str str)) + (chr (schar str 0)) + (end-string (and end-string (str end-string))) + (end-string-len (if end-string + (length end-string) + nil))) + (declare (type fixnum len)) + (cond ((and start-of-end-string-p case-insensitive-p) + ;; closure for the first STR which belongs to the constant + ;; string at the end of the regular expression; + ;; case-insensitive version + (lambda (start-pos) + (declare (type fixnum start-pos end-string-len)) + (let ((test-end-pos (+ start-pos end-string-len))) + (declare (type fixnum test-end-pos)) + ;; either we're at *END-STRING-POS* (which means that + ;; it has already been confirmed that end-string + ;; starts here) or we really have to test + (and (or (= start-pos *end-string-pos*) + (and (<= test-end-pos *end-pos*) + (*string*-equal end-string start-pos test-end-pos + 0 end-string-len))) + (funcall next-fn (+ start-pos len)))))) + (start-of-end-string-p + ;; closure for the first STR which belongs to the constant + ;; string at the end of the regular expression; + ;; case-sensitive version + (lambda (start-pos) + (declare (type fixnum start-pos end-string-len)) + (let ((test-end-pos (+ start-pos end-string-len))) + (declare (type fixnum test-end-pos)) + ;; either we're at *END-STRING-POS* (which means that + ;; it has already been confirmed that end-string + ;; starts here) or we really have to test + (and (or (= start-pos *end-string-pos*) + (and (<= test-end-pos *end-pos*) + (*string*= end-string start-pos test-end-pos + 0 end-string-len))) + (funcall next-fn (+ start-pos len)))))) + (skip + ;; a STR which can be skipped because some other function + ;; has already confirmed that it matches + (lambda (start-pos) + (declare (type fixnum start-pos)) + (funcall next-fn (+ start-pos len)))) + ((and (= len 1) case-insensitive-p) + ;; STR represent exactly one character; case-insensitive + ;; version + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (< start-pos *end-pos*) + (char-equal (schar *string* start-pos) chr) + (funcall next-fn (1+ start-pos))))) + ((= len 1) + ;; STR represent exactly one character; case-sensitive + ;; version + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (< start-pos *end-pos*) + (char= (schar *string* start-pos) chr) + (funcall next-fn (1+ start-pos))))) + (case-insensitive-p + ;; general case, case-insensitive version + (lambda (start-pos) + (declare (type fixnum start-pos)) + (let ((next-pos (+ start-pos len))) + (declare (type fixnum next-pos)) + (and (<= next-pos *end-pos*) + (*string*-equal str start-pos next-pos 0 len) + (funcall next-fn next-pos))))) + (t + ;; general case, case-sensitive version + (lambda (start-pos) + (declare (type fixnum start-pos)) + (let ((next-pos (+ start-pos len))) + (declare (type fixnum next-pos)) + (and (<= next-pos *end-pos*) + (*string*= str start-pos next-pos 0 len) + (funcall next-fn next-pos)))))))) + +(declaim (inline word-boundary-p)) + +(defun word-boundary-p (start-pos) + "Check whether START-POS is a word-boundary within *STRING*." + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (type fixnum start-pos)) + (let ((1-start-pos (1- start-pos))) + ;; either the character before START-POS is a word-constituent and + ;; the character at START-POS isn't... + (or (and (or (= start-pos *end-pos*) + (and (< start-pos *end-pos*) + (not (word-char-p (schar *string* start-pos))))) + (and (< 1-start-pos *end-pos*) + (<= *start-pos* 1-start-pos) + (word-char-p (schar *string* 1-start-pos)))) + ;; ...or vice versa + (and (or (= start-pos *start-pos*) + (and (< 1-start-pos *end-pos*) + (<= *start-pos* 1-start-pos) + (not (word-char-p (schar *string* 1-start-pos))))) + (and (< start-pos *end-pos*) + (word-char-p (schar *string* start-pos))))))) + +(defmethod create-matcher-aux ((word-boundary word-boundary) next-fn) + (declare (type function next-fn)) + (if (negatedp word-boundary) + (lambda (start-pos) + (and (not (word-boundary-p start-pos)) + (funcall next-fn start-pos))) + (lambda (start-pos) + (and (word-boundary-p start-pos) + (funcall next-fn start-pos))))) + +(defmethod create-matcher-aux ((everything everything) next-fn) + (declare (type function next-fn)) + (if (single-line-p everything) + ;; closure for single-line-mode: we really match everything, so we + ;; just advance the index into *STRING* by one and carry on + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (< start-pos *end-pos*) + (funcall next-fn (1+ start-pos)))) + ;; not single-line-mode, so we have to make sure we don't match + ;; #\Newline + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (< start-pos *end-pos*) + (char/= (schar *string* start-pos) #\Newline) + (funcall next-fn (1+ start-pos)))))) + +(defmethod create-matcher-aux ((anchor anchor) next-fn) + (declare (type function next-fn)) + (let ((startp (startp anchor)) + (multi-line-p (multi-line-p anchor))) + (cond ((no-newline-p anchor) + ;; this must be and end-anchor and it must be modeless, so + ;; we just have to check whether START-POS equals + ;; *END-POS* + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (= start-pos *end-pos*) + (funcall next-fn start-pos)))) + ((and startp multi-line-p) + ;; a start-anchor in multi-line-mode: check if we're at + ;; *START-POS* or if the last character was #\Newline + (lambda (start-pos) + (declare (type fixnum start-pos)) + (let ((*start-pos* (or *real-start-pos* *start-pos*))) + (and (or (= start-pos *start-pos*) + (and (<= start-pos *end-pos*) + (> start-pos *start-pos*) + (char= #\Newline + (schar *string* (1- start-pos))))) + (funcall next-fn start-pos))))) + (startp + ;; a start-anchor which is not in multi-line-mode, so just + ;; check whether we're at *START-POS* + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (= start-pos (or *real-start-pos* *start-pos*)) + (funcall next-fn start-pos)))) + (multi-line-p + ;; an end-anchor in multi-line-mode: check if we're at + ;; *END-POS* or if the character we're looking at is + ;; #\Newline + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (or (= start-pos *end-pos*) + (and (< start-pos *end-pos*) + (char= #\Newline + (schar *string* start-pos)))) + (funcall next-fn start-pos)))) + (t + ;; an end-anchor which is not in multi-line-mode, so just + ;; check if we're at *END-POS* or if we're looking at + ;; #\Newline and there's nothing behind it + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (or (= start-pos *end-pos*) + (and (= start-pos (1- *end-pos*)) + (char= #\Newline + (schar *string* start-pos)))) + (funcall next-fn start-pos))))))) + +(defmethod create-matcher-aux ((back-reference back-reference) next-fn) + (declare (type function next-fn)) + ;; the position of the corresponding REGISTER within the whole + ;; regex; we start to count at 0 + (let ((num (num back-reference))) + (if (case-insensitive-p back-reference) + ;; the case-insensitive version + (lambda (start-pos) + (declare (type fixnum start-pos)) + (let ((reg-start (svref *reg-starts* num)) + (reg-end (svref *reg-ends* num))) + ;; only bother to check if the corresponding REGISTER as + ;; matched successfully already + (and reg-start + (let ((next-pos (+ start-pos (- (the fixnum reg-end) + (the fixnum reg-start))))) + (declare (type fixnum next-pos)) + (and + (<= next-pos *end-pos*) + (*string*-equal *string* start-pos next-pos + reg-start reg-end) + (funcall next-fn next-pos)))))) + ;; the case-sensitive version + (lambda (start-pos) + (declare (type fixnum start-pos)) + (let ((reg-start (svref *reg-starts* num)) + (reg-end (svref *reg-ends* num))) + ;; only bother to check if the corresponding REGISTER as + ;; matched successfully already + (and reg-start + (let ((next-pos (+ start-pos (- (the fixnum reg-end) + (the fixnum reg-start))))) + (declare (type fixnum next-pos)) + (and + (<= next-pos *end-pos*) + (*string*= *string* start-pos next-pos + reg-start reg-end) + (funcall next-fn next-pos))))))))) + +(defmethod create-matcher-aux ((branch branch) next-fn) + (let* ((test (test branch)) + (then-matcher (create-matcher-aux (then-regex branch) next-fn)) + (else-matcher (create-matcher-aux (else-regex branch) next-fn))) + (declare (type function then-matcher else-matcher)) + (cond ((numberp test) + (lambda (start-pos) + (declare (type fixnum test)) + (if (and (< test (length *reg-starts*)) + (svref *reg-starts* test)) + (funcall then-matcher start-pos) + (funcall else-matcher start-pos)))) + (t + (let ((test-matcher (create-matcher-aux test #'identity))) + (declare (type function test-matcher)) + (lambda (start-pos) + (if (funcall test-matcher start-pos) + (funcall then-matcher start-pos) + (funcall else-matcher start-pos)))))))) + +(defmethod create-matcher-aux ((standalone standalone) next-fn) + (let ((inner-matcher (create-matcher-aux (regex standalone) #'identity))) + (declare (type function next-fn inner-matcher)) + (lambda (start-pos) + (let ((next-pos (funcall inner-matcher start-pos))) + (and next-pos + (funcall next-fn next-pos)))))) + +(defmethod create-matcher-aux ((filter filter) next-fn) + (let ((fn (fn filter))) + (lambda (start-pos) + (let ((next-pos (funcall fn start-pos))) + (and next-pos + (funcall next-fn next-pos)))))) + +(defmethod create-matcher-aux ((void void) next-fn) + ;; optimize away VOIDs: don't create a closure, just return NEXT-FN + next-fn) diff --git a/practicals/libraries/cl-ppcre-1.2.3/convert.lisp b/practicals/libraries/cl-ppcre-1.2.3/convert.lisp new file mode 100644 index 0000000..f137add --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/convert.lisp @@ -0,0 +1,788 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/convert.lisp,v 1.19 2004/10/14 12:40:39 edi Exp $ + +;;; Here the parse tree is converted into its internal representation +;;; using REGEX objects. At the same time some optimizations are +;;; already applied. + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre) + +;;; The flags that represent the "ism" modifiers are always kept +;;; together in a three-element list. We use the following macros to +;;; access individual elements. + +(defmacro case-insensitive-mode-p (flags) + "Accessor macro to extract the first flag out of a three-element flag list." + `(first ,flags)) + +(defmacro multi-line-mode-p (flags) + "Accessor macro to extract the second flag out of a three-element flag list." + `(second ,flags)) + +(defmacro single-line-mode-p (flags) + "Accessor macro to extract the third flag out of a three-element flag list." + `(third ,flags)) + +(defun set-flag (token) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (special flags)) + "Reads a flag token and sets or unsets the corresponding entry in +the special FLAGS list." + (case token + ((:case-insensitive-p) + (setf (case-insensitive-mode-p flags) t)) + ((:case-sensitive-p) + (setf (case-insensitive-mode-p flags) nil)) + ((:multi-line-mode-p) + (setf (multi-line-mode-p flags) t)) + ((:not-multi-line-mode-p) + (setf (multi-line-mode-p flags) nil)) + ((:single-line-mode-p) + (setf (single-line-mode-p flags) t)) + ((:not-single-line-mode-p) + (setf (single-line-mode-p flags) nil)) + (otherwise + (signal-ppcre-syntax-error "Unknown flag token ~A" token)))) + +(defun add-range-to-hash (hash from to) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (special flags)) + "Adds all characters from character FROM to character TO (inclusive) +to the char class hash HASH. Does the right thing with respect to +case-(in)sensitivity as specified by the special variable FLAGS." + (let ((from-code (char-code from)) + (to-code (char-code to))) + (when (> from-code to-code) + (signal-ppcre-syntax-error "Invalid range from ~A to ~A in char-class" + from to)) + (cond ((case-insensitive-mode-p flags) + (loop for code from from-code to to-code + for chr = (code-char code) + do (setf (gethash (char-upcase chr) hash) t + (gethash (char-downcase chr) hash) t))) + (t + (loop for code from from-code to to-code + do (setf (gethash (code-char code) hash) t)))) + hash)) + +(defun convert-char-class-to-hash (list) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Combines all items in LIST into one char class hash and returns it. +Items can be single characters, character ranges like \(:RANGE #\\A +#\\E), or special character classes like :DIGIT-CLASS. Does the right +thing with respect to case-\(in)sensitivity as specified by the +special variable FLAGS." + (loop with hash = (make-hash-table :size (ceiling (expt *regex-char-code-limit* (/ 1 4))) + :rehash-size (float (expt *regex-char-code-limit* (/ 1 4))) + :rehash-threshold #-genera 1.0 #+genera 0.99) + for item in list + if (characterp item) + ;; treat a single character C like a range (:RANGE C C) + do (add-range-to-hash hash item item) + else if (symbolp item) + ;; special character classes + do (setq hash + (case item + ((:digit-class) + (merge-hash hash +digit-hash+)) + ((:non-digit-class) + (merge-inverted-hash hash +digit-hash+)) + ((:whitespace-char-class) + (merge-hash hash +whitespace-char-hash+)) + ((:non-whitespace-char-class) + (merge-inverted-hash hash +whitespace-char-hash+)) + ((:word-char-class) + (merge-hash hash +word-char-hash+)) + ((:non-word-char-class) + (merge-inverted-hash hash +word-char-hash+)) + (otherwise + (signal-ppcre-syntax-error + "Unknown symbol ~A in character class" + item)))) + else if (and (consp item) + (eq (car item) :range)) + ;; proper ranges + do (add-range-to-hash hash + (second item) + (third item)) + else do (signal-ppcre-syntax-error "Unknown item ~A in char-class list" + item) + finally (return hash))) + +(defun maybe-split-repetition (regex + greedyp + minimum + maximum + min-len + length + reg-seen) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (type fixnum minimum) + (type (or fixnum null) maximum)) + "Splits a REPETITION object into a constant and a varying part if +applicable, i.e. something like + a{3,} -> a{3}a* +The arguments to this function correspond to the REPETITION slots of +the same name." + ;; note the usage of COPY-REGEX here; we can't use the same REGEX + ;; object in both REPETITIONS because they will have different + ;; offsets + (when maximum + (when (zerop maximum) + ;; trivial case: don't repeat at all + (return-from maybe-split-repetition + (make-instance 'void))) + (when (= 1 minimum maximum) + ;; another trivial case: "repeat" exactly once + (return-from maybe-split-repetition + regex))) + ;; first set up the constant part of the repetition + ;; maybe that's all we need + (let ((constant-repetition (if (plusp minimum) + (make-instance 'repetition + :regex (copy-regex regex) + :greedyp greedyp + :minimum minimum + :maximum minimum + :min-len min-len + :len length + :contains-register-p reg-seen) + ;; don't create garbage if minimum is 0 + nil))) + (when (and maximum + (= maximum minimum)) + (return-from maybe-split-repetition + ;; no varying part needed because min = max + constant-repetition)) + ;; now construct the varying part + (let ((varying-repetition + (make-instance 'repetition + :regex regex + :greedyp greedyp + :minimum 0 + :maximum (if maximum (- maximum minimum) nil) + :min-len min-len + :len length + :contains-register-p reg-seen))) + (cond ((zerop minimum) + ;; min = 0, no constant part needed + varying-repetition) + ((= 1 minimum) + ;; min = 1, constant part needs no REPETITION wrapped around + (make-instance 'seq + :elements (list (copy-regex regex) + varying-repetition))) + (t + ;; general case + (make-instance 'seq + :elements (list constant-repetition + varying-repetition))))))) + +;; During the conversion of the parse tree we keep track of the start +;; of the parse tree in the special variable STARTS-WITH which'll +;; either hold a STR object or an EVERYTHING object. The latter is the +;; case if the regex starts with ".*" which implicitely anchors the +;; regex at the start (perhaps modulo #\Newline). + +(defun maybe-accumulate (str) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (special accumulate-start-p starts-with)) + (declare (ftype (function (t) fixnum) len)) + "Accumulate STR into the special variable STARTS-WITH if +ACCUMULATE-START-P (also special) is true and STARTS-WITH is either +NIL or a STR object of the same case mode. Always returns NIL." + (when accumulate-start-p + (etypecase starts-with + (str + ;; STARTS-WITH already holds a STR, so we check if we can + ;; concatenate + (cond ((eq (case-insensitive-p starts-with) + (case-insensitive-p str)) + ;; we modify STARTS-WITH in place + (setf (len starts-with) + (+ (len starts-with) (len str))) + ;; note that we use SLOT-VALUE because the accessor + ;; STR has a declared FTYPE which doesn't fit here + (adjust-array (slot-value starts-with 'str) + (len starts-with) + :fill-pointer t) + (setf (subseq (slot-value starts-with 'str) + (- (len starts-with) (len str))) + (str str) + ;; STR objects that are parts of STARTS-WITH + ;; always have their SKIP slot set to true + ;; because the SCAN function will take care of + ;; them, i.e. the matcher can ignore them + (skip str) t)) + (t (setq accumulate-start-p nil)))) + (null + ;; STARTS-WITH is still empty, so we create a new STR object + (setf starts-with + (make-instance 'str + :str "" + :case-insensitive-p (case-insensitive-p str)) + ;; INITIALIZE-INSTANCE will coerce the STR to a simple + ;; string, so we have to fill it afterwards + (slot-value starts-with 'str) + (make-array (len str) + :initial-contents (str str) + :element-type 'character + :fill-pointer t + :adjustable t) + (len starts-with) + (len str) + ;; see remark about SKIP above + (skip str) t)) + (everything + ;; STARTS-WITH already holds an EVERYTHING object - we can't + ;; concatenate + (setq accumulate-start-p nil)))) + nil) + +(defun convert-aux (parse-tree) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (special flags reg-num accumulate-start-p starts-with max-back-ref)) + "Converts the parse tree PARSE-TREE into a REGEX object and returns it. + +Will also + - split and optimize repetitions, + - accumulate strings or EVERYTHING objects into the special variable + STARTS-WITH, + - keep track of all registers seen in the special variable REG-NUM, + - keep track of the highest backreference seen in the special + variable MAX-BACK-REF, + - maintain and adher to the currently applicable modifiers in the special + variable FLAGS, and + - maybe even wash your car..." + (cond ((consp parse-tree) + (case (first parse-tree) + ;; (:SEQUENCE {}*) + ((:sequence) + (cond ((cddr parse-tree) + ;; this is essentially like + ;; (MAPCAR 'CONVERT-AUX (REST PARSE-TREE)) + ;; but we don't cons a new list + (loop for parse-tree-rest on (rest parse-tree) + while parse-tree-rest + do (setf (car parse-tree-rest) + (convert-aux (car parse-tree-rest)))) + (make-instance 'seq + :elements (rest parse-tree))) + (t (convert-aux (second parse-tree))))) + ;; (:GROUP {}*) + ;; this is a syntactical construct equivalent to :SEQUENCE + ;; intended to keep the effect of modifiers local + ((:group) + ;; make a local copy of FLAGS and shadow the global + ;; value while we descend into the enclosed regexes + (let ((flags (copy-list flags))) + (declare (special flags)) + (cond ((cddr parse-tree) + (loop for parse-tree-rest on (rest parse-tree) + while parse-tree-rest + do (setf (car parse-tree-rest) + (convert-aux (car parse-tree-rest)))) + (make-instance 'seq + :elements (rest parse-tree))) + (t (convert-aux (second parse-tree)))))) + ;; (:ALTERNATION {}*) + ((:alternation) + ;; we must stop accumulating objects into STARTS-WITH + ;; once we reach an alternation + (setq accumulate-start-p nil) + (loop for parse-tree-rest on (rest parse-tree) + while parse-tree-rest + do (setf (car parse-tree-rest) + (convert-aux (car parse-tree-rest)))) + (make-instance 'alternation + :choices (rest parse-tree))) + ;; (:BRANCH ) + ;; must be look-ahead, look-behind or number; + ;; if is an alternation it must have one or two + ;; choices + ((:branch) + (setq accumulate-start-p nil) + (let* ((test-candidate (second parse-tree)) + (test (cond ((numberp test-candidate) + (when (zerop (the fixnum test-candidate)) + (signal-ppcre-syntax-error + "Register 0 doesn't exist: ~S" + parse-tree)) + (1- (the fixnum test-candidate))) + (t (convert-aux test-candidate)))) + (alternations (convert-aux (third parse-tree)))) + (when (and (not (numberp test)) + (not (typep test 'lookahead)) + (not (typep test 'lookbehind))) + (signal-ppcre-syntax-error + "Branch test must be look-ahead, look-behind or number: ~S" + parse-tree)) + (typecase alternations + (alternation + (case (length (choices alternations)) + ((0) + (signal-ppcre-syntax-error "No choices in branch: ~S" + parse-tree)) + ((1) + (make-instance 'branch + :test test + :then-regex (first + (choices alternations)))) + ((2) + (make-instance 'branch + :test test + :then-regex (first + (choices alternations)) + :else-regex (second + (choices alternations)))) + (otherwise + (signal-ppcre-syntax-error + "Too much choices in branch: ~S" + parse-tree)))) + (t + (make-instance 'branch + :test test + :then-regex alternations))))) + ;; (:POSITIVE-LOOKAHEAD|:NEGATIVE-LOOKAHEAD ) + ((:positive-lookahead :negative-lookahead) + ;; keep the effect of modifiers local to the enclosed + ;; regex and stop accumulating into STARTS-WITH + (setq accumulate-start-p nil) + (let ((flags (copy-list flags))) + (declare (special flags)) + (make-instance 'lookahead + :regex (convert-aux (second parse-tree)) + :positivep (eq (first parse-tree) + :positive-lookahead)))) + ;; (:POSITIVE-LOOKBEHIND|:NEGATIVE-LOOKBEHIND ) + ((:positive-lookbehind :negative-lookbehind) + ;; keep the effect of modifiers local to the enclosed + ;; regex and stop accumulating into STARTS-WITH + (setq accumulate-start-p nil) + (let* ((flags (copy-list flags)) + (regex (convert-aux (second parse-tree))) + (len (regex-length regex))) + (declare (special flags)) + ;; lookbehind assertions must be of fixed length + (unless len + (signal-ppcre-syntax-error + "Variable length look-behind not implemented (yet): ~S" + parse-tree)) + (make-instance 'lookbehind + :regex regex + :positivep (eq (first parse-tree) + :positive-lookbehind) + :len len))) + ;; (:GREEDY-REPETITION|:NON-GREEDY-REPETITION ) + ((:greedy-repetition :non-greedy-repetition) + ;; remember the value of ACCUMULATE-START-P upon entering + (let ((local-accumulate-start-p accumulate-start-p)) + (let ((minimum (second parse-tree)) + (maximum (third parse-tree))) + (declare (type fixnum minimum)) + (declare (type (or null fixnum) maximum)) + (unless (and maximum + (= 1 minimum maximum)) + ;; set ACCUMULATE-START-P to NIL for the rest of + ;; the conversion because we can't continue to + ;; accumulate inside as well as after a proper + ;; repetition + (setq accumulate-start-p nil)) + (let* (reg-seen + (regex (convert-aux (fourth parse-tree))) + (min-len (regex-min-length regex)) + (greedyp (eq (first parse-tree) :greedy-repetition)) + (length (regex-length regex))) + ;; note that this declaration already applies to + ;; the call to CONVERT-AUX above + (declare (special reg-seen)) + (when (and local-accumulate-start-p + (not starts-with) + (zerop minimum) + (not maximum)) + ;; if this repetition is (equivalent to) ".*" + ;; and if we're at the start of the regex we + ;; remember it for ADVANCE-FN (see the SCAN + ;; function) + (setq starts-with (everythingp regex))) + (if (or (not reg-seen) + (not greedyp) + (not length) + (zerop length) + (and maximum (= minimum maximum))) + ;; the repetition doesn't enclose a register, or + ;; it's not greedy, or we can't determine it's + ;; (inner) length, or the length is zero, or the + ;; number of repetitions is fixed; in all of + ;; these cases we don't bother to optimize + (maybe-split-repetition regex + greedyp + minimum + maximum + min-len + length + reg-seen) + ;; otherwise we make a transformation that looks + ;; roughly like one of + ;; * -> (?:*)? + ;; + -> * + ;; where the trick is that as much as possible + ;; registers from are removed in + ;; + (let* (reg-seen ; new instance for REMOVE-REGISTERS + (remove-registers-p t) + (inner-regex (remove-registers regex)) + (inner-repetition + ;; this is the "" part + (maybe-split-repetition inner-regex + ;; always greedy + t + ;; reduce minimum by 1 + ;; unless it's already 0 + (if (zerop minimum) + 0 + (1- minimum)) + ;; reduce maximum by 1 + ;; unless it's NIL + (and maximum + (1- maximum)) + min-len + length + reg-seen)) + (inner-seq + ;; this is the "*" part + (make-instance 'seq + :elements (list inner-repetition + regex)))) + ;; note that this declaration already applies + ;; to the call to REMOVE-REGISTERS above + (declare (special remove-registers-p reg-seen)) + ;; wrap INNER-SEQ with a greedy + ;; {0,1}-repetition (i.e. "?") if necessary + (if (plusp minimum) + inner-seq + (maybe-split-repetition inner-seq + t + 0 + 1 + min-len + nil + t)))))))) + ;; (:REGISTER ) + ((:register) + ;; keep the effect of modifiers local to the enclosed + ;; regex; also, assign the current value of REG-NUM to + ;; the corresponding slot of the REGISTER object and + ;; increase this counter afterwards + (let ((flags (copy-list flags)) + (stored-reg-num reg-num)) + (declare (special flags reg-seen)) + (setq reg-seen t) + (incf (the fixnum reg-num)) + (make-instance 'register + :regex (convert-aux (second parse-tree)) + :num stored-reg-num))) + ;; (:FILTER &optional ) + ((:filter) + ;; stop accumulating into STARTS-WITH + (setq accumulate-start-p nil) + (make-instance 'filter + :fn (second parse-tree) + :len (third parse-tree))) + ;; (:STANDALONE ) + ((:standalone) + ;; stop accumulating into STARTS-WITH + (setq accumulate-start-p nil) + ;; keep the effect of modifiers local to the enclosed + ;; regex + (let ((flags (copy-list flags))) + (declare (special flags)) + (make-instance 'standalone + :regex (convert-aux (second parse-tree))))) + ;; (:BACK-REFERENCE ) + ((:back-reference) + (let ((backref-number (second parse-tree))) + (declare (type fixnum backref-number)) + (when (or (not (typep backref-number 'fixnum)) + (<= backref-number 0)) + (signal-ppcre-syntax-error + "Illegal back-reference: ~S" + parse-tree)) + ;; stop accumulating into STARTS-WITH and increase + ;; MAX-BACK-REF if necessary + (setq accumulate-start-p nil + max-back-ref (max (the fixnum max-back-ref) + backref-number)) + (make-instance 'back-reference + ;; we start counting from 0 internally + :num (1- backref-number) + :case-insensitive-p (case-insensitive-mode-p + flags)))) + ;; (:CHAR-CLASS|:INVERTED-CHAR-CLASS {}*) + ;; where item is one of + ;; - a character + ;; - a character range: (:RANGE ) + ;; - a special char class symbol like :DIGIT-CHAR-CLASS + ((:char-class :inverted-char-class) + ;; first create the hash-table and some auxiliary values + (let* (hash + hash-keys + (count most-positive-fixnum) + (item-list (rest parse-tree)) + (invertedp (eq (first parse-tree) :inverted-char-class)) + word-char-class-p) + (cond ((every (lambda (item) (eq item :word-char-class)) + item-list) + ;; treat "[\\w]" like "\\w" + (setq word-char-class-p t)) + ((every (lambda (item) (eq item :non-word-char-class)) + item-list) + ;; treat "[\\W]" like "\\W" + (setq word-char-class-p t) + (setq invertedp (not invertedp))) + (t + (setq hash (convert-char-class-to-hash item-list) + count (hash-table-count hash)) + (when (<= count 2) + ;; collect the hash-table keys into a list if + ;; COUNT is smaller than 3 + (setq hash-keys + (loop for chr being the hash-keys of hash + collect chr))))) + (cond ((and (not invertedp) + (= count 1)) + ;; convert one-element hash table into a STR + ;; object and try to accumulate into + ;; STARTS-WITH + (let ((str (make-instance 'str + :str (string + (first hash-keys)) + :case-insensitive-p nil))) + (maybe-accumulate str) + str)) + ((and (not invertedp) + (= count 2) + (char-equal (first hash-keys) (second hash-keys))) + ;; convert two-element hash table into a + ;; case-insensitive STR object and try to + ;; accumulate into STARTS-WITH if the two + ;; characters are CHAR-EQUAL + (let ((str (make-instance 'str + :str (string + (first hash-keys)) + :case-insensitive-p t))) + (maybe-accumulate str) + str)) + (t + ;; the general case; stop accumulating into STARTS-WITH + (setq accumulate-start-p nil) + (make-instance 'char-class + :hash hash + :case-insensitive-p + (case-insensitive-mode-p flags) + :invertedp invertedp + :word-char-class-p word-char-class-p))))) + ;; (:FLAGS {}*) + ;; where flag is a modifier symbol like :CASE-INSENSITIVE-P + ((:flags) + ;; set/unset the flags corresponding to the symbols + ;; following :FLAGS + (mapc #'set-flag (rest parse-tree)) + ;; we're only interested in the side effect of + ;; setting/unsetting the flags and turn this syntactical + ;; construct into a VOID object which'll be optimized + ;; away when creating the matcher + (make-instance 'void)) + (otherwise + (signal-ppcre-syntax-error + "Unknown token ~A in parse-tree" + (first parse-tree))))) + ((or (characterp parse-tree) (stringp parse-tree)) + ;; turn characters or strings into STR objects and try to + ;; accumulate into STARTS-WITH + (let ((str (make-instance 'str + :str (string parse-tree) + :case-insensitive-p + (case-insensitive-mode-p flags)))) + (maybe-accumulate str) + str)) + (t + ;; and now for the tokens which are symbols + (case parse-tree + ((:void) + (make-instance 'void)) + ((:word-boundary) + (make-instance 'word-boundary :negatedp nil)) + ((:non-word-boundary) + (make-instance 'word-boundary :negatedp t)) + ;; the special character classes + ((:digit-class + :non-digit-class + :word-char-class + :non-word-char-class + :whitespace-char-class + :non-whitespace-char-class) + ;; stop accumulating into STARTS-WITH + (setq accumulate-start-p nil) + (make-instance 'char-class + ;; use the constants defined in util.lisp + :hash (case parse-tree + ((:digit-class + :non-digit-class) + +digit-hash+) + ((:word-char-class + :non-word-char-class) + nil) + ((:whitespace-char-class + :non-whitespace-char-class) + +whitespace-char-hash+)) + ;; this value doesn't really matter but + ;; NIL should result in slightly faster + ;; matchers + :case-insensitive-p nil + :invertedp (member parse-tree + '(:non-digit-class + :non-word-char-class + :non-whitespace-char-class) + :test #'eq) + :word-char-class-p (member parse-tree + '(:word-char-class + :non-word-char-class) + :test #'eq))) + ((:start-anchor ; Perl's "^" + :end-anchor ; Perl's "$" + :modeless-end-anchor-no-newline + ; Perl's "\z" + :modeless-start-anchor ; Perl's "\A" + :modeless-end-anchor) ; Perl's "\Z" + (make-instance 'anchor + :startp (member parse-tree + '(:start-anchor + :modeless-start-anchor) + :test #'eq) + ;; set this value according to the + ;; current settings of FLAGS (unless it's + ;; a modeless anchor) + :multi-line-p + (and (multi-line-mode-p flags) + (not (member parse-tree + '(:modeless-start-anchor + :modeless-end-anchor + :modeless-end-anchor-no-newline) + :test #'eq))) + :no-newline-p + (eq parse-tree + :modeless-end-anchor-no-newline))) + ((:everything) + ;; stop accumulating into STARTS-WITHS + (setq accumulate-start-p nil) + (make-instance 'everything + :single-line-p (single-line-mode-p flags))) + ;; special tokens corresponding to Perl's "ism" modifiers + ((:case-insensitive-p + :case-sensitive-p + :multi-line-mode-p + :not-multi-line-mode-p + :single-line-mode-p + :not-single-line-mode-p) + ;; we're only interested in the side effect of + ;; setting/unsetting the flags and turn these tokens + ;; into VOID objects which'll be optimized away when + ;; creating the matcher + (set-flag parse-tree) + (make-instance 'void)) + (otherwise + (let ((translation (and (symbolp parse-tree) + (parse-tree-synonym parse-tree)))) + (if translation + (convert-aux (copy-tree translation)) + (signal-ppcre-syntax-error "Unknown token ~A in parse-tree" + parse-tree)))))))) + +(defun convert (parse-tree) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Converts the parse tree PARSE-TREE into an equivalent REGEX object +and returns three values: the REGEX object, the number of registers +seen and an object the regex starts with which is either a STR object +or an EVERYTHING object (if the regex starts with something like +\".*\") or NIL." + ;; this function basically just initializes the special variables + ;; and then calls CONVERT-AUX to do all the work + (let* ((flags (list nil nil nil)) + (reg-num 0) + (accumulate-start-p t) + starts-with + (max-back-ref 0) + (converted-parse-tree (convert-aux parse-tree))) + (declare (special flags reg-num accumulate-start-p starts-with max-back-ref)) + ;; make sure we don't reference registers which aren't there + (when (> (the fixnum max-back-ref) + (the fixnum reg-num)) + (signal-ppcre-syntax-error + "Backreference to register ~A which has not been defined" + max-back-ref)) + (when (typep starts-with 'str) + (setf (slot-value starts-with 'str) + (coerce (slot-value starts-with 'str) 'simple-string))) + (values converted-parse-tree reg-num starts-with))) diff --git a/practicals/libraries/cl-ppcre-1.2.3/doc/benchmarks.2002-12-22.txt b/practicals/libraries/cl-ppcre-1.2.3/doc/benchmarks.2002-12-22.txt new file mode 100644 index 0000000..907dc53 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/doc/benchmarks.2002-12-22.txt @@ -0,0 +1,1546 @@ + 1: 0.2862 (100000 repetitions, Perl: 0.2097 seconds, CL-PPCRE: 0.0600 seconds) + 2: 0.4161 (1000000 repetitions, Perl: 0.7690 seconds, CL-PPCRE: 0.3200 seconds) + 3: 0.3939 (100000 repetitions, Perl: 0.2031 seconds, CL-PPCRE: 0.0800 seconds) + 4: 0.4639 (1000000 repetitions, Perl: 0.7976 seconds, CL-PPCRE: 0.3700 seconds) + 5: 0.4400 (100000 repetitions, Perl: 0.1591 seconds, CL-PPCRE: 0.0700 seconds) + 6: 0.5106 (100000 repetitions, Perl: 0.1567 seconds, CL-PPCRE: 0.0800 seconds) + 7: 0.4928 (100000 repetitions, Perl: 0.1826 seconds, CL-PPCRE: 0.0900 seconds) + 8: 0.5934 (100000 repetitions, Perl: 0.1854 seconds, CL-PPCRE: 0.1100 seconds) + 9: 0.3450 (100000 repetitions, Perl: 0.2029 seconds, CL-PPCRE: 0.0700 seconds) + 10: 0.5261 (100000 repetitions, Perl: 0.3231 seconds, CL-PPCRE: 0.1700 seconds) + 11: 0.5556 (100000 repetitions, Perl: 0.3240 seconds, CL-PPCRE: 0.1800 seconds) + 12: 0.5490 (100000 repetitions, Perl: 0.3279 seconds, CL-PPCRE: 0.1800 seconds) + 13: 0.5595 (100000 repetitions, Perl: 0.3217 seconds, CL-PPCRE: 0.1800 seconds) + 14: 0.5917 (100000 repetitions, Perl: 0.3211 seconds, CL-PPCRE: 0.1900 seconds) + 15: 0.5164 (100000 repetitions, Perl: 0.3292 seconds, CL-PPCRE: 0.1700 seconds) + 16: 0.5552 (100000 repetitions, Perl: 0.3242 seconds, CL-PPCRE: 0.1800 seconds) + 17: 0.5273 (100000 repetitions, Perl: 0.3224 seconds, CL-PPCRE: 0.1700 seconds) + 18: 0.5886 (100000 repetitions, Perl: 0.3228 seconds, CL-PPCRE: 0.1900 seconds) + 19: 0.5524 (100000 repetitions, Perl: 0.3259 seconds, CL-PPCRE: 0.1800 seconds) + 20: 0.5860 (100000 repetitions, Perl: 0.3242 seconds, CL-PPCRE: 0.1900 seconds) + 21: 0.5569 (100000 repetitions, Perl: 0.3232 seconds, CL-PPCRE: 0.1800 seconds) + 22: 0.6129 (100000 repetitions, Perl: 0.3263 seconds, CL-PPCRE: 0.2000 seconds) + 23: 0.5789 (100000 repetitions, Perl: 0.3282 seconds, CL-PPCRE: 0.1900 seconds) + 24: 0.5516 (100000 repetitions, Perl: 0.3263 seconds, CL-PPCRE: 0.1800 seconds) + 25: 0.4861 (100000 repetitions, Perl: 0.3291 seconds, CL-PPCRE: 0.1600 seconds) + 26: 0.4879 (100000 repetitions, Perl: 0.3279 seconds, CL-PPCRE: 0.1600 seconds) + 27: 0.4929 (100000 repetitions, Perl: 0.3246 seconds, CL-PPCRE: 0.1600 seconds) + 28: 0.5633 (100000 repetitions, Perl: 0.3195 seconds, CL-PPCRE: 0.1800 seconds) + 29: 0.4901 (100000 repetitions, Perl: 0.3264 seconds, CL-PPCRE: 0.1600 seconds) + 30: 0.5145 (100000 repetitions, Perl: 0.3304 seconds, CL-PPCRE: 0.1700 seconds) + 31: 0.5286 (100000 repetitions, Perl: 0.3216 seconds, CL-PPCRE: 0.1700 seconds) + 32: 0.5306 (100000 repetitions, Perl: 0.3204 seconds, CL-PPCRE: 0.1700 seconds) + 33: 0.5213 (100000 repetitions, Perl: 0.3261 seconds, CL-PPCRE: 0.1700 seconds) + 34: 0.5221 (100000 repetitions, Perl: 0.3256 seconds, CL-PPCRE: 0.1700 seconds) + 35: 0.5858 (100000 repetitions, Perl: 0.3243 seconds, CL-PPCRE: 0.1900 seconds) + 36: 0.5556 (100000 repetitions, Perl: 0.3240 seconds, CL-PPCRE: 0.1800 seconds) + 37: 0.6985 (100000 repetitions, Perl: 0.3293 seconds, CL-PPCRE: 0.2300 seconds) + 38: 0.5760 (100000 repetitions, Perl: 0.3299 seconds, CL-PPCRE: 0.1900 seconds) + 39: 0.6964 (100000 repetitions, Perl: 0.3303 seconds, CL-PPCRE: 0.2300 seconds) + 40: 1.2660 (1000000 repetitions, Perl: 0.7662 seconds, CL-PPCRE: 0.9700 seconds) + 41: 1.5983 (1000000 repetitions, Perl: 0.8509 seconds, CL-PPCRE: 1.3600 seconds) + 42: 1.3381 (1000000 repetitions, Perl: 0.7697 seconds, CL-PPCRE: 1.0300 seconds) + 43: 1.0846 (100000 repetitions, Perl: 0.7284 seconds, CL-PPCRE: 0.7900 seconds) + 44: 0.9248 (100000 repetitions, Perl: 0.7029 seconds, CL-PPCRE: 0.6500 seconds) + 45: 0.9872 (100000 repetitions, Perl: 0.6281 seconds, CL-PPCRE: 0.6200 seconds) + 46: 0.4932 (100000 repetitions, Perl: 0.1622 seconds, CL-PPCRE: 0.0800 seconds) + 47: 0.5567 (100000 repetitions, Perl: 0.1617 seconds, CL-PPCRE: 0.0900 seconds) + 48: 0.7445 (1000000 repetitions, Perl: 0.6179 seconds, CL-PPCRE: 0.4600 seconds) + 49: 1.4152 (1000000 repetitions, Perl: 0.8055 seconds, CL-PPCRE: 1.1400 seconds) + 50: 0.6042 (100000 repetitions, Perl: 0.1324 seconds, CL-PPCRE: 0.0800 seconds) + 51: 0.3376 (100000 repetitions, Perl: 0.2370 seconds, CL-PPCRE: 0.0800 seconds) + 52: 0.3549 (100000 repetitions, Perl: 0.3099 seconds, CL-PPCRE: 0.1100 seconds) + 53: 0.3404 (100000 repetitions, Perl: 0.3525 seconds, CL-PPCRE: 0.1200 seconds) + 54: 0.3398 (100000 repetitions, Perl: 0.3237 seconds, CL-PPCRE: 0.1100 seconds) + 55: 0.3516 (100000 repetitions, Perl: 0.4551 seconds, CL-PPCRE: 0.1600 seconds) + 56: 0.3069 (100000 repetitions, Perl: 0.3258 seconds, CL-PPCRE: 0.1000 seconds) + 57: 0.3032 (100000 repetitions, Perl: 0.6925 seconds, CL-PPCRE: 0.2100 seconds) + 58: 0.3515 (10000 repetitions, Perl: 0.3130 seconds, CL-PPCRE: 0.1100 seconds) + 59: 0.3563 (100000 repetitions, Perl: 0.3088 seconds, CL-PPCRE: 0.1100 seconds) + 60: 0.3429 (100000 repetitions, Perl: 0.6708 seconds, CL-PPCRE: 0.2300 seconds) + 61: 0.3169 (100000 repetitions, Perl: 0.2840 seconds, CL-PPCRE: 0.0900 seconds) + 62: 0.3519 (100000 repetitions, Perl: 0.2842 seconds, CL-PPCRE: 0.1000 seconds) + 63: 0.3443 (100000 repetitions, Perl: 0.2904 seconds, CL-PPCRE: 0.1000 seconds) + 64: 0.3917 (100000 repetitions, Perl: 0.2808 seconds, CL-PPCRE: 0.1100 seconds) + 65: 0.3474 (100000 repetitions, Perl: 0.2878 seconds, CL-PPCRE: 0.1000 seconds) + 66: 0.3473 (100000 repetitions, Perl: 0.2879 seconds, CL-PPCRE: 0.1000 seconds) + 67: 0.4047 (100000 repetitions, Perl: 0.2965 seconds, CL-PPCRE: 0.1200 seconds) + 68: 0.4057 (100000 repetitions, Perl: 0.2958 seconds, CL-PPCRE: 0.1200 seconds) + 69: 0.4091 (100000 repetitions, Perl: 0.2689 seconds, CL-PPCRE: 0.1100 seconds) + 70: 0.4841 (100000 repetitions, Perl: 0.4751 seconds, CL-PPCRE: 0.2300 seconds) + 71: 0.2327 (100000 repetitions, Perl: 0.3438 seconds, CL-PPCRE: 0.0800 seconds) + 72: 0.4767 (100000 repetitions, Perl: 0.3986 seconds, CL-PPCRE: 0.1900 seconds) + 73: 0.3673 (100000 repetitions, Perl: 0.5174 seconds, CL-PPCRE: 0.1900 seconds) + 74: 0.5311 (100000 repetitions, Perl: 0.5460 seconds, CL-PPCRE: 0.2900 seconds) + 75: 0.5722 (100000 repetitions, Perl: 0.5068 seconds, CL-PPCRE: 0.2900 seconds) + 76: 0.5913 (100000 repetitions, Perl: 0.5074 seconds, CL-PPCRE: 0.3000 seconds) + 77: 0.3544 (100000 repetitions, Perl: 0.2257 seconds, CL-PPCRE: 0.0800 seconds) + 78: 0.3919 (100000 repetitions, Perl: 0.4593 seconds, CL-PPCRE: 0.1800 seconds) + 79: 0.4080 (100000 repetitions, Perl: 0.2941 seconds, CL-PPCRE: 0.1200 seconds) + 80: 0.5635 (100000 repetitions, Perl: 0.5147 seconds, CL-PPCRE: 0.2900 seconds) + 81: 0.5616 (100000 repetitions, Perl: 0.5163 seconds, CL-PPCRE: 0.2900 seconds) + 82: 0.4216 (100000 repetitions, Perl: 0.1423 seconds, CL-PPCRE: 0.0600 seconds) + 83: 0.2502 (100000 repetitions, Perl: 0.1199 seconds, CL-PPCRE: 0.0300 seconds) + 84: 0.2546 (100000 repetitions, Perl: 0.1178 seconds, CL-PPCRE: 0.0300 seconds) + 85: 0.2515 (100000 repetitions, Perl: 0.1193 seconds, CL-PPCRE: 0.0300 seconds) + 86: 0.2545 (100000 repetitions, Perl: 0.1179 seconds, CL-PPCRE: 0.0300 seconds) + 87: 0.2535 (100000 repetitions, Perl: 0.1184 seconds, CL-PPCRE: 0.0300 seconds) + 88: 0.2522 (100000 repetitions, Perl: 0.1189 seconds, CL-PPCRE: 0.0300 seconds) + 89: 0.3010 (1000000 repetitions, Perl: 0.8971 seconds, CL-PPCRE: 0.2700 seconds) + 90: 0.2906 (1000000 repetitions, Perl: 0.8947 seconds, CL-PPCRE: 0.2600 seconds) + 91: 0.2800 (1000000 repetitions, Perl: 0.8928 seconds, CL-PPCRE: 0.2500 seconds) + 92: 0.3329 (100000 repetitions, Perl: 0.1202 seconds, CL-PPCRE: 0.0400 seconds) + 93: 0.3394 (100000 repetitions, Perl: 0.1178 seconds, CL-PPCRE: 0.0400 seconds) + 94: 0.2516 (100000 repetitions, Perl: 0.1193 seconds, CL-PPCRE: 0.0300 seconds) + 95: 0.3393 (100000 repetitions, Perl: 0.1179 seconds, CL-PPCRE: 0.0400 seconds) + 96: 0.2891 (1000000 repetitions, Perl: 0.8994 seconds, CL-PPCRE: 0.2600 seconds) + 97: 0.3026 (1000000 repetitions, Perl: 0.8922 seconds, CL-PPCRE: 0.2700 seconds) + 98: 0.2508 (100000 repetitions, Perl: 0.1196 seconds, CL-PPCRE: 0.0300 seconds) + 99: 0.2546 (100000 repetitions, Perl: 0.1178 seconds, CL-PPCRE: 0.0300 seconds) + 100: 0.2493 (100000 repetitions, Perl: 0.1204 seconds, CL-PPCRE: 0.0300 seconds) + 101: 0.3002 (1000000 repetitions, Perl: 0.8994 seconds, CL-PPCRE: 0.2700 seconds) + 102: 0.2904 (1000000 repetitions, Perl: 0.8954 seconds, CL-PPCRE: 0.2600 seconds) + 103: 0.2904 (1000000 repetitions, Perl: 0.8952 seconds, CL-PPCRE: 0.2600 seconds) + 104: 0.2976 (1000000 repetitions, Perl: 0.9073 seconds, CL-PPCRE: 0.2700 seconds) + 105: 0.2999 (1000000 repetitions, Perl: 0.9004 seconds, CL-PPCRE: 0.2700 seconds) + 106: 0.2885 (1000000 repetitions, Perl: 0.9012 seconds, CL-PPCRE: 0.2600 seconds) + 107: 0.2505 (100000 repetitions, Perl: 0.1198 seconds, CL-PPCRE: 0.0300 seconds) + 108: 0.3368 (100000 repetitions, Perl: 0.1188 seconds, CL-PPCRE: 0.0400 seconds) + 109: 0.3018 (1000000 repetitions, Perl: 0.8945 seconds, CL-PPCRE: 0.2700 seconds) + 110: 0.2893 (1000000 repetitions, Perl: 0.8988 seconds, CL-PPCRE: 0.2600 seconds) + 111: 0.3013 (1000000 repetitions, Perl: 0.8963 seconds, CL-PPCRE: 0.2700 seconds) + 112: 0.2876 (1000000 repetitions, Perl: 0.9039 seconds, CL-PPCRE: 0.2600 seconds) + 113: 0.4585 (100000 repetitions, Perl: 0.1309 seconds, CL-PPCRE: 0.0600 seconds) + 114: 0.3816 (100000 repetitions, Perl: 0.1310 seconds, CL-PPCRE: 0.0500 seconds) + 115: 0.2148 (100000 repetitions, Perl: 0.1397 seconds, CL-PPCRE: 0.0300 seconds) + 116: 0.2182 (100000 repetitions, Perl: 0.1375 seconds, CL-PPCRE: 0.0300 seconds) + 117: 0.2147 (100000 repetitions, Perl: 0.1397 seconds, CL-PPCRE: 0.0300 seconds) + 118: 0.2154 (100000 repetitions, Perl: 0.1393 seconds, CL-PPCRE: 0.0300 seconds) + 119: 0.2180 (100000 repetitions, Perl: 0.1376 seconds, CL-PPCRE: 0.0300 seconds) + 120: 0.2171 (100000 repetitions, Perl: 0.1382 seconds, CL-PPCRE: 0.0300 seconds) + 121: 0.2145 (100000 repetitions, Perl: 0.1398 seconds, CL-PPCRE: 0.0300 seconds) + 122: 0.2184 (100000 repetitions, Perl: 0.1374 seconds, CL-PPCRE: 0.0300 seconds) + 123: 0.2172 (100000 repetitions, Perl: 0.1381 seconds, CL-PPCRE: 0.0300 seconds) + 124: 0.2124 (100000 repetitions, Perl: 0.1412 seconds, CL-PPCRE: 0.0300 seconds) + 125: 0.2146 (100000 repetitions, Perl: 0.1398 seconds, CL-PPCRE: 0.0300 seconds) + 126: 0.2834 (100000 repetitions, Perl: 0.1412 seconds, CL-PPCRE: 0.0400 seconds) + 127: 0.2649 (1000000 repetitions, Perl: 0.9439 seconds, CL-PPCRE: 0.2500 seconds) + 128: 0.3613 (100000 repetitions, Perl: 0.1384 seconds, CL-PPCRE: 0.0500 seconds) + 129: 0.2925 (100000 repetitions, Perl: 0.1367 seconds, CL-PPCRE: 0.0400 seconds) + 130: 0.2868 (100000 repetitions, Perl: 0.1394 seconds, CL-PPCRE: 0.0400 seconds) + 131: 0.3982 (100000 repetitions, Perl: 0.1758 seconds, CL-PPCRE: 0.0700 seconds) + 132: 0.3910 (100000 repetitions, Perl: 0.1790 seconds, CL-PPCRE: 0.0700 seconds) + 133: 0.4550 (1000000 repetitions, Perl: 0.6154 seconds, CL-PPCRE: 0.2800 seconds) + 134: 0.2943 (100000 repetitions, Perl: 0.1699 seconds, CL-PPCRE: 0.0500 seconds) + 135: 0.2965 (100000 repetitions, Perl: 0.1686 seconds, CL-PPCRE: 0.0500 seconds) + 136: 0.2959 (100000 repetitions, Perl: 0.1690 seconds, CL-PPCRE: 0.0500 seconds) + 137: 0.3398 (1000000 repetitions, Perl: 0.6180 seconds, CL-PPCRE: 0.2100 seconds) + 138: 0.2963 (100000 repetitions, Perl: 0.1687 seconds, CL-PPCRE: 0.0500 seconds) + 139: 0.3538 (100000 repetitions, Perl: 0.1413 seconds, CL-PPCRE: 0.0500 seconds) + 140: 0.3339 (100000 repetitions, Perl: 0.1498 seconds, CL-PPCRE: 0.0500 seconds) + 141: 0.3863 (100000 repetitions, Perl: 0.1812 seconds, CL-PPCRE: 0.0700 seconds) + 142: 0.3245 (1000000 repetitions, Perl: 0.6163 seconds, CL-PPCRE: 0.2000 seconds) + 143: 0.3688 (100000 repetitions, Perl: 0.1627 seconds, CL-PPCRE: 0.0600 seconds) + 144: 0.3063 (100000 repetitions, Perl: 0.4571 seconds, CL-PPCRE: 0.1400 seconds) + 145: 0.7234 (100000 repetitions, Perl: 0.1244 seconds, CL-PPCRE: 0.0900 seconds) + 146: 0.2700 (100000 repetitions, Perl: 0.4074 seconds, CL-PPCRE: 0.1100 seconds) + 147: 0.8323 (1000000 repetitions, Perl: 0.8771 seconds, CL-PPCRE: 0.7300 seconds) + 148: 0.6980 (1000000 repetitions, Perl: 0.7880 seconds, CL-PPCRE: 0.5500 seconds) + 149: 0.4197 (100000 repetitions, Perl: 0.1668 seconds, CL-PPCRE: 0.0700 seconds) + 150: 0.5716 (1000000 repetitions, Perl: 0.8223 seconds, CL-PPCRE: 0.4700 seconds) + 151: 0.5047 (100000 repetitions, Perl: 0.1585 seconds, CL-PPCRE: 0.0800 seconds) + 152: 0.5141 (100000 repetitions, Perl: 0.1556 seconds, CL-PPCRE: 0.0800 seconds) + 153: 0.5116 (100000 repetitions, Perl: 0.1564 seconds, CL-PPCRE: 0.0800 seconds) + 154: 0.4508 (100000 repetitions, Perl: 0.1553 seconds, CL-PPCRE: 0.0700 seconds) + 155: 0.5214 (100000 repetitions, Perl: 0.1534 seconds, CL-PPCRE: 0.0800 seconds) + 156: 0.6360 (100000 repetitions, Perl: 0.1730 seconds, CL-PPCRE: 0.1100 seconds) + 157: 0.9536 (100000 repetitions, Perl: 0.2202 seconds, CL-PPCRE: 0.2100 seconds) + 158: 1.0349 (100000 repetitions, Perl: 0.2416 seconds, CL-PPCRE: 0.2500 seconds) + 159: 1.0302 (100000 repetitions, Perl: 0.1262 seconds, CL-PPCRE: 0.1300 seconds) + 160: 1.1893 (1000000 repetitions, Perl: 0.8325 seconds, CL-PPCRE: 0.9900 seconds) + 161: 1.2895 (100000 repetitions, Perl: 0.1473 seconds, CL-PPCRE: 0.1900 seconds) + 162: 1.3938 (100000 repetitions, Perl: 0.2152 seconds, CL-PPCRE: 0.3000 seconds) + 163: 0.3708 (100000 repetitions, Perl: 0.3505 seconds, CL-PPCRE: 0.1300 seconds) + 164: 0.4182 (100000 repetitions, Perl: 0.3826 seconds, CL-PPCRE: 0.1600 seconds) + 165: 0.4926 (100000 repetitions, Perl: 0.4060 seconds, CL-PPCRE: 0.2000 seconds) + 166: 0.9852 (1000000 repetitions, Perl: 0.6192 seconds, CL-PPCRE: 0.6100 seconds) + 167: 0.9454 (1000000 repetitions, Perl: 0.8039 seconds, CL-PPCRE: 0.7600 seconds) + 168: 0.7178 (100000 repetitions, Perl: 0.3483 seconds, CL-PPCRE: 0.2500 seconds) + 169: 0.8758 (100000 repetitions, Perl: 0.3426 seconds, CL-PPCRE: 0.3000 seconds) + 170: 1.0131 (1000000 repetitions, Perl: 0.8292 seconds, CL-PPCRE: 0.8400 seconds) + 171: 0.3196 (100000 repetitions, Perl: 0.2503 seconds, CL-PPCRE: 0.0800 seconds) + 172: 0.3538 (100000 repetitions, Perl: 0.2544 seconds, CL-PPCRE: 0.0900 seconds) + 173: 0.3592 (100000 repetitions, Perl: 0.2506 seconds, CL-PPCRE: 0.0900 seconds) + 174: 0.6737 (100000 repetitions, Perl: 0.3117 seconds, CL-PPCRE: 0.2100 seconds) + 175: 0.5639 (100000 repetitions, Perl: 0.4078 seconds, CL-PPCRE: 0.2300 seconds) + 176: 0.5225 (100000 repetitions, Perl: 0.3062 seconds, CL-PPCRE: 0.1600 seconds) + 177: 0.4419 (100000 repetitions, Perl: 0.1131 seconds, CL-PPCRE: 0.0500 seconds) + 178: 0.4992 (100000 repetitions, Perl: 0.2604 seconds, CL-PPCRE: 0.1300 seconds) + 179: 0.4653 (100000 repetitions, Perl: 0.3009 seconds, CL-PPCRE: 0.1400 seconds) + 180: 0.4438 (100000 repetitions, Perl: 0.4056 seconds, CL-PPCRE: 0.1800 seconds) + 181: 0.4672 (100000 repetitions, Perl: 0.4281 seconds, CL-PPCRE: 0.2000 seconds) + 182: 0.7833 (100000 repetitions, Perl: 0.1149 seconds, CL-PPCRE: 0.0900 seconds) + 183: 0.5458 (100000 repetitions, Perl: 0.2382 seconds, CL-PPCRE: 0.1300 seconds) + 184: 0.4734 (100000 repetitions, Perl: 0.4436 seconds, CL-PPCRE: 0.2100 seconds) + 185: 0.5420 (100000 repetitions, Perl: 0.3137 seconds, CL-PPCRE: 0.1700 seconds) + 186: 0.7234 (100000 repetitions, Perl: 0.2074 seconds, CL-PPCRE: 0.1500 seconds) + 187: 0.7521 (100000 repetitions, Perl: 0.2393 seconds, CL-PPCRE: 0.1800 seconds) + 188: 0.6819 (100000 repetitions, Perl: 0.2053 seconds, CL-PPCRE: 0.1400 seconds) + 189: 0.4950 (100000 repetitions, Perl: 0.2020 seconds, CL-PPCRE: 0.1000 seconds) + 190: 0.4918 (100000 repetitions, Perl: 0.2033 seconds, CL-PPCRE: 0.1000 seconds) + 191: 0.5343 (100000 repetitions, Perl: 0.2433 seconds, CL-PPCRE: 0.1300 seconds) + 192: 0.4148 (100000 repetitions, Perl: 0.2411 seconds, CL-PPCRE: 0.1000 seconds) + 193: 0.4709 (100000 repetitions, Perl: 0.2761 seconds, CL-PPCRE: 0.1300 seconds) + 194: 0.5928 (100000 repetitions, Perl: 0.2868 seconds, CL-PPCRE: 0.1700 seconds) + 195: 0.5643 (100000 repetitions, Perl: 0.2835 seconds, CL-PPCRE: 0.1600 seconds) + 196: 0.2465 (100000 repetitions, Perl: 0.1217 seconds, CL-PPCRE: 0.0300 seconds) + 197: 0.4772 (100000 repetitions, Perl: 0.1467 seconds, CL-PPCRE: 0.0700 seconds) + 198: 0.4983 (1000000 repetitions, Perl: 0.6221 seconds, CL-PPCRE: 0.3100 seconds) + 199: 0.2375 (100000 repetitions, Perl: 0.1263 seconds, CL-PPCRE: 0.0300 seconds) + 200: 0.4759 (100000 repetitions, Perl: 0.1471 seconds, CL-PPCRE: 0.0700 seconds) + 201: 0.4963 (1000000 repetitions, Perl: 0.6247 seconds, CL-PPCRE: 0.3100 seconds) + 202: 0.2370 (100000 repetitions, Perl: 0.1266 seconds, CL-PPCRE: 0.0300 seconds) + 203: 0.5375 (100000 repetitions, Perl: 0.1488 seconds, CL-PPCRE: 0.0800 seconds) + 204: 0.4682 (100000 repetitions, Perl: 0.1495 seconds, CL-PPCRE: 0.0700 seconds) + 205: 0.4859 (1000000 repetitions, Perl: 0.6174 seconds, CL-PPCRE: 0.3000 seconds) + 206: 0.5685 (1000000 repetitions, Perl: 0.6156 seconds, CL-PPCRE: 0.3500 seconds) + 207: 1.1822 (100000 repetitions, Perl: 0.2622 seconds, CL-PPCRE: 0.3100 seconds) + 208: 0.8749 (100000 repetitions, Perl: 0.2400 seconds, CL-PPCRE: 0.2100 seconds) + 209: 0.8621 (100000 repetitions, Perl: 0.1392 seconds, CL-PPCRE: 0.1200 seconds) + 210: 2.0520 (100000 repetitions, Perl: 0.1511 seconds, CL-PPCRE: 0.3100 seconds) + 211: 0.2312 (100000 repetitions, Perl: 0.1297 seconds, CL-PPCRE: 0.0300 seconds) + 212: 0.3110 (100000 repetitions, Perl: 0.1286 seconds, CL-PPCRE: 0.0400 seconds) + 213: 0.3096 (100000 repetitions, Perl: 0.1292 seconds, CL-PPCRE: 0.0400 seconds) + 214: 0.2972 (100000 repetitions, Perl: 0.1346 seconds, CL-PPCRE: 0.0400 seconds) + 215: 0.2916 (100000 repetitions, Perl: 0.1372 seconds, CL-PPCRE: 0.0400 seconds) + 216: 0.2908 (100000 repetitions, Perl: 0.1376 seconds, CL-PPCRE: 0.0400 seconds) + 217: 0.3625 (100000 repetitions, Perl: 0.1379 seconds, CL-PPCRE: 0.0500 seconds) + 218: 0.2910 (100000 repetitions, Perl: 0.1374 seconds, CL-PPCRE: 0.0400 seconds) + 219: 0.2351 (100000 repetitions, Perl: 0.1276 seconds, CL-PPCRE: 0.0300 seconds) + 220: 0.3128 (100000 repetitions, Perl: 0.1279 seconds, CL-PPCRE: 0.0400 seconds) + 221: 0.3099 (100000 repetitions, Perl: 0.1291 seconds, CL-PPCRE: 0.0400 seconds) + 222: 0.3134 (100000 repetitions, Perl: 0.1277 seconds, CL-PPCRE: 0.0400 seconds) + 223: 0.3118 (100000 repetitions, Perl: 0.1283 seconds, CL-PPCRE: 0.0400 seconds) + 224: 0.3115 (100000 repetitions, Perl: 0.1284 seconds, CL-PPCRE: 0.0400 seconds) + 225: 0.3098 (100000 repetitions, Perl: 0.1291 seconds, CL-PPCRE: 0.0400 seconds) + 226: 0.3118 (100000 repetitions, Perl: 0.1283 seconds, CL-PPCRE: 0.0400 seconds) + 227: 0.2644 (100000 repetitions, Perl: 0.1513 seconds, CL-PPCRE: 0.0400 seconds) + 228: 0.2621 (100000 repetitions, Perl: 0.1526 seconds, CL-PPCRE: 0.0400 seconds) + 229: 0.1883 (100000 repetitions, Perl: 0.1593 seconds, CL-PPCRE: 0.0300 seconds) + 230: 0.2480 (100000 repetitions, Perl: 0.1613 seconds, CL-PPCRE: 0.0400 seconds) + 231: 0.2458 (100000 repetitions, Perl: 0.1627 seconds, CL-PPCRE: 0.0400 seconds) + 232: 0.1954 (100000 repetitions, Perl: 0.1535 seconds, CL-PPCRE: 0.0300 seconds) + 233: 0.1929 (100000 repetitions, Perl: 0.1555 seconds, CL-PPCRE: 0.0300 seconds) + 234: 0.1934 (100000 repetitions, Perl: 0.1551 seconds, CL-PPCRE: 0.0300 seconds) + 235: 0.2597 (100000 repetitions, Perl: 0.1540 seconds, CL-PPCRE: 0.0400 seconds) + 236: 0.2556 (100000 repetitions, Perl: 0.1565 seconds, CL-PPCRE: 0.0400 seconds) + 237: 0.3496 (100000 repetitions, Perl: 0.1430 seconds, CL-PPCRE: 0.0500 seconds) + 238: 0.3485 (100000 repetitions, Perl: 0.1435 seconds, CL-PPCRE: 0.0500 seconds) + 239: 0.3473 (100000 repetitions, Perl: 0.1440 seconds, CL-PPCRE: 0.0500 seconds) + 240: 0.3362 (1000000 repetitions, Perl: 0.6246 seconds, CL-PPCRE: 0.2100 seconds) + 241: 0.9108 (100000 repetitions, Perl: 0.1427 seconds, CL-PPCRE: 0.1300 seconds) + 242: 0.8320 (100000 repetitions, Perl: 0.1442 seconds, CL-PPCRE: 0.1200 seconds) + 243: 0.9578 (100000 repetitions, Perl: 0.1462 seconds, CL-PPCRE: 0.1400 seconds) + 244: 0.9571 (100000 repetitions, Perl: 0.1463 seconds, CL-PPCRE: 0.1400 seconds) + 245: 1.3241 (100000 repetitions, Perl: 0.1133 seconds, CL-PPCRE: 0.1500 seconds) + 246: 0.8377 (100000 repetitions, Perl: 0.1433 seconds, CL-PPCRE: 0.1200 seconds) + 247: 0.8486 (100000 repetitions, Perl: 0.1414 seconds, CL-PPCRE: 0.1200 seconds) + 248: 0.8450 (100000 repetitions, Perl: 0.1420 seconds, CL-PPCRE: 0.1200 seconds) + 249: 0.8369 (100000 repetitions, Perl: 0.1434 seconds, CL-PPCRE: 0.1200 seconds) + 250: 0.8463 (100000 repetitions, Perl: 0.1418 seconds, CL-PPCRE: 0.1200 seconds) + 251: 0.6517 (100000 repetitions, Perl: 0.2762 seconds, CL-PPCRE: 0.1800 seconds) + 252: 0.6811 (100000 repetitions, Perl: 0.2937 seconds, CL-PPCRE: 0.2000 seconds) + 253: 0.6578 (100000 repetitions, Perl: 0.1824 seconds, CL-PPCRE: 0.1200 seconds) + 254: 0.8682 (100000 repetitions, Perl: 0.3571 seconds, CL-PPCRE: 0.3100 seconds) + 255: 0.7904 (100000 repetitions, Perl: 0.4175 seconds, CL-PPCRE: 0.3300 seconds) + 256: 0.8379 (100000 repetitions, Perl: 0.2745 seconds, CL-PPCRE: 0.2300 seconds) + 257: 0.7974 (100000 repetitions, Perl: 0.3010 seconds, CL-PPCRE: 0.2400 seconds) + 258: 0.8064 (100000 repetitions, Perl: 0.2852 seconds, CL-PPCRE: 0.2300 seconds) + 259: 0.7055 (100000 repetitions, Perl: 0.2977 seconds, CL-PPCRE: 0.2100 seconds) + 260: 0.8818 (100000 repetitions, Perl: 0.3515 seconds, CL-PPCRE: 0.3100 seconds) + 261: 0.8762 (100000 repetitions, Perl: 0.3652 seconds, CL-PPCRE: 0.3200 seconds) + 262: 0.8611 (100000 repetitions, Perl: 0.3020 seconds, CL-PPCRE: 0.2600 seconds) + 263: 0.5267 (100000 repetitions, Perl: 0.1519 seconds, CL-PPCRE: 0.0800 seconds) + 264: 0.5322 (100000 repetitions, Perl: 0.1503 seconds, CL-PPCRE: 0.0800 seconds) + 265: 0.9607 (100000 repetitions, Perl: 0.3123 seconds, CL-PPCRE: 0.3000 seconds) + 266: 0.4526 (100000 repetitions, Perl: 0.2872 seconds, CL-PPCRE: 0.1300 seconds) + 267: 0.6699 (100000 repetitions, Perl: 0.5673 seconds, CL-PPCRE: 0.3800 seconds) + 268: 0.5854 (100000 repetitions, Perl: 0.2221 seconds, CL-PPCRE: 0.1300 seconds) + 269: 0.5397 (100000 repetitions, Perl: 0.2223 seconds, CL-PPCRE: 0.1200 seconds) + 270: 0.5484 (100000 repetitions, Perl: 0.2188 seconds, CL-PPCRE: 0.1200 seconds) + 271: 0.4907 (100000 repetitions, Perl: 0.1834 seconds, CL-PPCRE: 0.0900 seconds) + 272: 0.5724 (100000 repetitions, Perl: 0.1922 seconds, CL-PPCRE: 0.1100 seconds) + 273: 0.4339 (100000 repetitions, Perl: 0.1383 seconds, CL-PPCRE: 0.0600 seconds) + 274: 0.4306 (100000 repetitions, Perl: 0.1394 seconds, CL-PPCRE: 0.0600 seconds) + 275: 0.2869 (100000 repetitions, Perl: 0.1743 seconds, CL-PPCRE: 0.0500 seconds) + 276: 0.4362 (100000 repetitions, Perl: 0.1376 seconds, CL-PPCRE: 0.0600 seconds) + 277: 0.7754 (100000 repetitions, Perl: 0.2321 seconds, CL-PPCRE: 0.1800 seconds) + 278: 0.7791 (100000 repetitions, Perl: 0.2310 seconds, CL-PPCRE: 0.1800 seconds) + 279: 0.7789 (100000 repetitions, Perl: 0.2311 seconds, CL-PPCRE: 0.1800 seconds) + 280: 0.7811 (100000 repetitions, Perl: 0.2305 seconds, CL-PPCRE: 0.1800 seconds) + 281: 0.2450 (100000 repetitions, Perl: 0.2040 seconds, CL-PPCRE: 0.0500 seconds) + 282: 0.2661 (100000 repetitions, Perl: 0.1503 seconds, CL-PPCRE: 0.0400 seconds) + 283: 0.2589 (100000 repetitions, Perl: 0.1931 seconds, CL-PPCRE: 0.0500 seconds) + 284: 0.3521 (100000 repetitions, Perl: 0.1420 seconds, CL-PPCRE: 0.0500 seconds) + 285: 0.3907 (100000 repetitions, Perl: 0.1791 seconds, CL-PPCRE: 0.0700 seconds) + 286: 0.4476 (100000 repetitions, Perl: 0.1787 seconds, CL-PPCRE: 0.0800 seconds) + 287: 0.4616 (100000 repetitions, Perl: 0.1733 seconds, CL-PPCRE: 0.0800 seconds) + 288: 0.4378 (100000 repetitions, Perl: 0.1827 seconds, CL-PPCRE: 0.0800 seconds) + 289: 0.6693 (10000 repetitions, Perl: 0.1643 seconds, CL-PPCRE: 0.1100 seconds) + 290: 0.6433 (100000 repetitions, Perl: 0.9328 seconds, CL-PPCRE: 0.6000 seconds) + 291: 0.5793 (100000 repetitions, Perl: 0.7940 seconds, CL-PPCRE: 0.4600 seconds) + 292: 0.6398 (10000 repetitions, Perl: 0.2657 seconds, CL-PPCRE: 0.1700 seconds) + 293: 0.7511 (10000 repetitions, Perl: 0.3062 seconds, CL-PPCRE: 0.2300 seconds) + 294: 0.7114 (10000 repetitions, Perl: 0.2249 seconds, CL-PPCRE: 0.1600 seconds) + 295: 0.8033 (1000 repetitions, Perl: 0.2739 seconds, CL-PPCRE: 0.2200 seconds) + 296: 0.6041 (1000 repetitions, Perl: 0.1655 seconds, CL-PPCRE: 0.1000 seconds) + 297: 0.8512 (10000 repetitions, Perl: 0.1175 seconds, CL-PPCRE: 0.1000 seconds) + 298: 0.6747 (100000 repetitions, Perl: 0.7707 seconds, CL-PPCRE: 0.5200 seconds) + 299: 0.6291 (100000 repetitions, Perl: 0.6359 seconds, CL-PPCRE: 0.4000 seconds) + 300: 0.7881 (10000 repetitions, Perl: 0.1650 seconds, CL-PPCRE: 0.1300 seconds) + 301: 0.8624 (10000 repetitions, Perl: 0.2087 seconds, CL-PPCRE: 0.1800 seconds) + 302: 1.6513 (100000 repetitions, Perl: 0.7509 seconds, CL-PPCRE: 1.2400 seconds) + 303: 0.8539 (1000 repetitions, Perl: 0.2342 seconds, CL-PPCRE: 0.2000 seconds) + 304: 0.5071 (1000 repetitions, Perl: 0.1578 seconds, CL-PPCRE: 0.0800 seconds) + 305: 0.2994 (100000 repetitions, Perl: 0.2004 seconds, CL-PPCRE: 0.0600 seconds) + 306: 0.3442 (100000 repetitions, Perl: 0.2034 seconds, CL-PPCRE: 0.0700 seconds) + 307: 0.3386 (100000 repetitions, Perl: 0.2067 seconds, CL-PPCRE: 0.0700 seconds) + 308: 0.4439 (100000 repetitions, Perl: 0.2027 seconds, CL-PPCRE: 0.0900 seconds) + 309: 0.2541 (100000 repetitions, Perl: 0.1181 seconds, CL-PPCRE: 0.0300 seconds) + 310: 0.2507 (100000 repetitions, Perl: 0.1197 seconds, CL-PPCRE: 0.0300 seconds) + 311: 0.2546 (100000 repetitions, Perl: 0.1178 seconds, CL-PPCRE: 0.0300 seconds) + 312: 0.3225 (100000 repetitions, Perl: 0.1240 seconds, CL-PPCRE: 0.0400 seconds) + 313: 0.2763 (100000 repetitions, Perl: 0.2171 seconds, CL-PPCRE: 0.0600 seconds) + 314: 0.3364 (100000 repetitions, Perl: 0.2081 seconds, CL-PPCRE: 0.0700 seconds) + 315: 0.5995 (1000000 repetitions, Perl: 0.6171 seconds, CL-PPCRE: 0.3700 seconds) + 316: 0.6933 (100000 repetitions, Perl: 0.1010 seconds, CL-PPCRE: 0.0700 seconds) + 317: 0.7320 (100000 repetitions, Perl: 0.1639 seconds, CL-PPCRE: 0.1200 seconds) + 318: 0.6441 (100000 repetitions, Perl: 0.1708 seconds, CL-PPCRE: 0.1100 seconds) + 319: 0.7726 (100000 repetitions, Perl: 0.1553 seconds, CL-PPCRE: 0.1200 seconds) + 320: 0.2550 (100000 repetitions, Perl: 0.1176 seconds, CL-PPCRE: 0.0300 seconds) + 321: 0.2523 (100000 repetitions, Perl: 0.1189 seconds, CL-PPCRE: 0.0300 seconds) + 322: 0.3355 (100000 repetitions, Perl: 0.1192 seconds, CL-PPCRE: 0.0400 seconds) + 323: 0.2535 (100000 repetitions, Perl: 0.1184 seconds, CL-PPCRE: 0.0300 seconds) + 324: 0.2537 (100000 repetitions, Perl: 0.1182 seconds, CL-PPCRE: 0.0300 seconds) + 325: 0.3130 (1000000 repetitions, Perl: 0.8945 seconds, CL-PPCRE: 0.2800 seconds) + 326: 0.4343 (100000 repetitions, Perl: 0.1381 seconds, CL-PPCRE: 0.0600 seconds) + 327: 0.4595 (100000 repetitions, Perl: 0.1959 seconds, CL-PPCRE: 0.0900 seconds) + 328: 0.5075 (100000 repetitions, Perl: 0.2562 seconds, CL-PPCRE: 0.1300 seconds) + 329: 0.4848 (100000 repetitions, Perl: 0.2063 seconds, CL-PPCRE: 0.1000 seconds) + 330: 0.5754 (100000 repetitions, Perl: 0.2259 seconds, CL-PPCRE: 0.1300 seconds) + 331: 0.4784 (100000 repetitions, Perl: 0.2090 seconds, CL-PPCRE: 0.1000 seconds) + 332: 0.4854 (100000 repetitions, Perl: 0.2472 seconds, CL-PPCRE: 0.1200 seconds) + 333: 0.5108 (100000 repetitions, Perl: 0.1958 seconds, CL-PPCRE: 0.1000 seconds) + 334: 0.5869 (100000 repetitions, Perl: 0.1874 seconds, CL-PPCRE: 0.1100 seconds) + 335: 0.4115 (100000 repetitions, Perl: 0.1944 seconds, CL-PPCRE: 0.0800 seconds) + 336: 0.4591 (100000 repetitions, Perl: 0.1960 seconds, CL-PPCRE: 0.0900 seconds) + 337: 0.4391 (100000 repetitions, Perl: 0.2050 seconds, CL-PPCRE: 0.0900 seconds) + 338: 0.4906 (100000 repetitions, Perl: 0.2242 seconds, CL-PPCRE: 0.1100 seconds) + 339: 0.6043 (100000 repetitions, Perl: 0.1986 seconds, CL-PPCRE: 0.1200 seconds) + 340: 0.6038 (100000 repetitions, Perl: 0.1988 seconds, CL-PPCRE: 0.1200 seconds) + 341: 0.6465 (100000 repetitions, Perl: 0.2011 seconds, CL-PPCRE: 0.1300 seconds) + 342: 0.7695 (100000 repetitions, Perl: 0.2079 seconds, CL-PPCRE: 0.1600 seconds) + 343: 0.7205 (100000 repetitions, Perl: 0.2221 seconds, CL-PPCRE: 0.1600 seconds) + 344: 0.6924 (100000 repetitions, Perl: 0.2166 seconds, CL-PPCRE: 0.1500 seconds) + 345: 0.6438 (100000 repetitions, Perl: 0.2174 seconds, CL-PPCRE: 0.1400 seconds) + 346: 0.7015 (100000 repetitions, Perl: 0.1996 seconds, CL-PPCRE: 0.1400 seconds) + 347: 0.7526 (100000 repetitions, Perl: 0.1993 seconds, CL-PPCRE: 0.1500 seconds) + 348: 0.8079 (100000 repetitions, Perl: 0.2104 seconds, CL-PPCRE: 0.1700 seconds) + 349: 0.7955 (100000 repetitions, Perl: 0.2514 seconds, CL-PPCRE: 0.2000 seconds) + 350: 0.4692 (100000 repetitions, Perl: 0.1492 seconds, CL-PPCRE: 0.0700 seconds) + 351: 0.4673 (100000 repetitions, Perl: 0.1498 seconds, CL-PPCRE: 0.0700 seconds) + 352: 0.4633 (100000 repetitions, Perl: 0.1511 seconds, CL-PPCRE: 0.0700 seconds) + 353: 0.6346 (1000000 repetitions, Perl: 0.6145 seconds, CL-PPCRE: 0.3900 seconds) + 354: 1.1542 (1000000 repetitions, Perl: 0.9097 seconds, CL-PPCRE: 1.0500 seconds) + 355: 0.4759 (100000 repetitions, Perl: 0.2732 seconds, CL-PPCRE: 0.1300 seconds) + 356: 0.6078 (100000 repetitions, Perl: 0.2303 seconds, CL-PPCRE: 0.1400 seconds) + 357: 0.6025 (100000 repetitions, Perl: 0.2324 seconds, CL-PPCRE: 0.1400 seconds) + 358: 0.3389 (100000 repetitions, Perl: 0.1475 seconds, CL-PPCRE: 0.0500 seconds) + 359: 0.2653 (1000000 repetitions, Perl: 0.9424 seconds, CL-PPCRE: 0.2500 seconds) + 360: 0.3383 (100000 repetitions, Perl: 0.1478 seconds, CL-PPCRE: 0.0500 seconds) + 361: 0.4024 (100000 repetitions, Perl: 0.1491 seconds, CL-PPCRE: 0.0600 seconds) + 362: 0.3396 (100000 repetitions, Perl: 0.1472 seconds, CL-PPCRE: 0.0500 seconds) + 363: 0.4028 (100000 repetitions, Perl: 0.1489 seconds, CL-PPCRE: 0.0600 seconds) + 364: 0.2647 (100000 repetitions, Perl: 0.1511 seconds, CL-PPCRE: 0.0400 seconds) + 365: 0.3107 (100000 repetitions, Perl: 0.1609 seconds, CL-PPCRE: 0.0500 seconds) + 366: 0.3260 (100000 repetitions, Perl: 0.1534 seconds, CL-PPCRE: 0.0500 seconds) + 367: 0.3047 (100000 repetitions, Perl: 0.1641 seconds, CL-PPCRE: 0.0500 seconds) + 368: 0.4269 (100000 repetitions, Perl: 0.1405 seconds, CL-PPCRE: 0.0600 seconds) + 369: 0.6208 (1000000 repetitions, Perl: 0.7249 seconds, CL-PPCRE: 0.4500 seconds) + 370: 0.7444 (1000000 repetitions, Perl: 0.7254 seconds, CL-PPCRE: 0.5400 seconds) + 371: 0.6080 (1000000 repetitions, Perl: 0.7237 seconds, CL-PPCRE: 0.4400 seconds) + 372: 0.4148 (100000 repetitions, Perl: 0.1446 seconds, CL-PPCRE: 0.0600 seconds) + 373: 0.3998 (100000 repetitions, Perl: 0.1501 seconds, CL-PPCRE: 0.0600 seconds) + 374: 0.5947 (1000000 repetitions, Perl: 0.7903 seconds, CL-PPCRE: 0.4700 seconds) + 375: 0.6556 (1000000 repetitions, Perl: 0.7932 seconds, CL-PPCRE: 0.5200 seconds) + 376: 0.5811 (1000000 repetitions, Perl: 0.7916 seconds, CL-PPCRE: 0.4600 seconds) + 377: 0.5095 (100000 repetitions, Perl: 0.1374 seconds, CL-PPCRE: 0.0700 seconds) + 378: 0.7533 (100000 repetitions, Perl: 0.1327 seconds, CL-PPCRE: 0.1000 seconds) + 379: 0.2212 (100000 repetitions, Perl: 0.1356 seconds, CL-PPCRE: 0.0300 seconds) + 380: 0.2732 (100000 repetitions, Perl: 0.1830 seconds, CL-PPCRE: 0.0500 seconds) + 381: 0.3535 (100000 repetitions, Perl: 0.1414 seconds, CL-PPCRE: 0.0500 seconds) + 382: 0.3386 (1000000 repetitions, Perl: 0.7974 seconds, CL-PPCRE: 0.2700 seconds) + 383: 0.3481 (100000 repetitions, Perl: 0.1436 seconds, CL-PPCRE: 0.0500 seconds) + 384: 0.3376 (1000000 repetitions, Perl: 0.7998 seconds, CL-PPCRE: 0.2700 seconds) + 385: 0.2810 (100000 repetitions, Perl: 0.1424 seconds, CL-PPCRE: 0.0400 seconds) + 386: 0.3465 (1000000 repetitions, Perl: 0.8081 seconds, CL-PPCRE: 0.2800 seconds) + 387: 0.2732 (100000 repetitions, Perl: 0.1464 seconds, CL-PPCRE: 0.0400 seconds) + 388: 0.2781 (100000 repetitions, Perl: 0.1438 seconds, CL-PPCRE: 0.0400 seconds) + 389: 0.4344 (1000000 repetitions, Perl: 0.8288 seconds, CL-PPCRE: 0.3600 seconds) + 390: 0.3457 (100000 repetitions, Perl: 0.1446 seconds, CL-PPCRE: 0.0500 seconds) + 391: 0.5038 (1000000 repetitions, Perl: 0.8337 seconds, CL-PPCRE: 0.4200 seconds) + 392: 0.2577 (100000 repetitions, Perl: 0.1552 seconds, CL-PPCRE: 0.0400 seconds) + 393: 0.2542 (100000 repetitions, Perl: 0.1573 seconds, CL-PPCRE: 0.0400 seconds) + 394: 0.4403 (1000000 repetitions, Perl: 0.7722 seconds, CL-PPCRE: 0.3400 seconds) + 395: 0.5672 (100000 repetitions, Perl: 0.1587 seconds, CL-PPCRE: 0.0900 seconds) + 396: 0.6214 (100000 repetitions, Perl: 0.1609 seconds, CL-PPCRE: 0.1000 seconds) + 397: 0.5460 (100000 repetitions, Perl: 0.1648 seconds, CL-PPCRE: 0.0900 seconds) + 398: 0.2812 (100000 repetitions, Perl: 0.1778 seconds, CL-PPCRE: 0.0500 seconds) + 399: 0.2775 (100000 repetitions, Perl: 0.1802 seconds, CL-PPCRE: 0.0500 seconds) + 400: 0.3287 (100000 repetitions, Perl: 0.1825 seconds, CL-PPCRE: 0.0600 seconds) + 401: 0.2684 (100000 repetitions, Perl: 0.1863 seconds, CL-PPCRE: 0.0500 seconds) + 402: 0.4942 (100000 repetitions, Perl: 0.1416 seconds, CL-PPCRE: 0.0700 seconds) + 403: 0.5378 (100000 repetitions, Perl: 0.1116 seconds, CL-PPCRE: 0.0600 seconds) + 404: 0.2952 (100000 repetitions, Perl: 0.1694 seconds, CL-PPCRE: 0.0500 seconds) + 405: 0.2887 (100000 repetitions, Perl: 0.1732 seconds, CL-PPCRE: 0.0500 seconds) + 406: 0.6374 (1000000 repetitions, Perl: 0.7844 seconds, CL-PPCRE: 0.5000 seconds) + 407: 0.4260 (100000 repetitions, Perl: 0.1878 seconds, CL-PPCRE: 0.0800 seconds) + 408: 0.4368 (100000 repetitions, Perl: 0.1832 seconds, CL-PPCRE: 0.0800 seconds) + 409: 0.4269 (100000 repetitions, Perl: 0.1874 seconds, CL-PPCRE: 0.0800 seconds) + 410: 0.3848 (100000 repetitions, Perl: 0.1819 seconds, CL-PPCRE: 0.0700 seconds) + 411: 0.4387 (100000 repetitions, Perl: 0.1824 seconds, CL-PPCRE: 0.0800 seconds) + 412: 0.4306 (100000 repetitions, Perl: 0.1858 seconds, CL-PPCRE: 0.0800 seconds) + 413: 0.4817 (100000 repetitions, Perl: 0.1868 seconds, CL-PPCRE: 0.0900 seconds) + 414: 0.4738 (100000 repetitions, Perl: 0.1900 seconds, CL-PPCRE: 0.0900 seconds) + 415: 0.4302 (100000 repetitions, Perl: 0.1860 seconds, CL-PPCRE: 0.0800 seconds) + 416: 0.4258 (100000 repetitions, Perl: 0.1879 seconds, CL-PPCRE: 0.0800 seconds) + 417: 0.4302 (100000 repetitions, Perl: 0.1860 seconds, CL-PPCRE: 0.0800 seconds) + 418: 0.2241 (100000 repetitions, Perl: 0.1785 seconds, CL-PPCRE: 0.0400 seconds) + 419: 0.2783 (100000 repetitions, Perl: 0.1796 seconds, CL-PPCRE: 0.0500 seconds) + 420: 0.2807 (100000 repetitions, Perl: 0.1781 seconds, CL-PPCRE: 0.0500 seconds) + 421: 0.2787 (100000 repetitions, Perl: 0.1794 seconds, CL-PPCRE: 0.0500 seconds) + 422: 0.7300 (100000 repetitions, Perl: 0.3425 seconds, CL-PPCRE: 0.2500 seconds) + 423: 0.8544 (100000 repetitions, Perl: 0.3160 seconds, CL-PPCRE: 0.2700 seconds) + 424: 0.2787 (100000 repetitions, Perl: 0.1794 seconds, CL-PPCRE: 0.0500 seconds) + 425: 0.2306 (100000 repetitions, Perl: 0.1734 seconds, CL-PPCRE: 0.0400 seconds) + 426: 0.3410 (100000 repetitions, Perl: 0.2053 seconds, CL-PPCRE: 0.0700 seconds) + 427: 0.2799 (100000 repetitions, Perl: 0.1786 seconds, CL-PPCRE: 0.0500 seconds) + 428: 0.2829 (100000 repetitions, Perl: 0.1767 seconds, CL-PPCRE: 0.0500 seconds) + 429: 0.4273 (100000 repetitions, Perl: 0.1872 seconds, CL-PPCRE: 0.0800 seconds) + 431: 0.6052 (100000 repetitions, Perl: 0.1983 seconds, CL-PPCRE: 0.1200 seconds) + 432: 0.6033 (100000 repetitions, Perl: 0.1989 seconds, CL-PPCRE: 0.1200 seconds) + 433: 0.6306 (100000 repetitions, Perl: 0.2220 seconds, CL-PPCRE: 0.1400 seconds) + 434: 0.6084 (100000 repetitions, Perl: 0.1972 seconds, CL-PPCRE: 0.1200 seconds) + 435: 0.7267 (1000000 repetitions, Perl: 0.9632 seconds, CL-PPCRE: 0.7000 seconds) + 436: 0.9658 (1000000 repetitions, Perl: 0.6316 seconds, CL-PPCRE: 0.6100 seconds) + 437: 0.7902 (100000 repetitions, Perl: 0.1519 seconds, CL-PPCRE: 0.1200 seconds) + 438: 0.2423 (100000 repetitions, Perl: 0.1238 seconds, CL-PPCRE: 0.0300 seconds) + 439: 0.3170 (100000 repetitions, Perl: 0.1262 seconds, CL-PPCRE: 0.0400 seconds) + 440: 0.2741 (100000 repetitions, Perl: 0.1459 seconds, CL-PPCRE: 0.0400 seconds) + 441: 0.4055 (100000 repetitions, Perl: 0.1480 seconds, CL-PPCRE: 0.0600 seconds) + 442: 0.2719 (100000 repetitions, Perl: 0.1471 seconds, CL-PPCRE: 0.0400 seconds) + 443: 0.2952 (100000 repetitions, Perl: 0.1355 seconds, CL-PPCRE: 0.0400 seconds) + 444: 0.3922 (1000000 repetitions, Perl: 0.8924 seconds, CL-PPCRE: 0.3500 seconds) + 445: 0.2694 (100000 repetitions, Perl: 0.1485 seconds, CL-PPCRE: 0.0400 seconds) + 446: 0.2717 (100000 repetitions, Perl: 0.1472 seconds, CL-PPCRE: 0.0400 seconds) + 447: 0.2136 (100000 repetitions, Perl: 0.1872 seconds, CL-PPCRE: 0.0400 seconds) + 448: 0.2401 (100000 repetitions, Perl: 0.1249 seconds, CL-PPCRE: 0.0300 seconds) + 449: 0.2930 (100000 repetitions, Perl: 0.1024 seconds, CL-PPCRE: 0.0300 seconds) + 450: 0.2929 (100000 repetitions, Perl: 0.1024 seconds, CL-PPCRE: 0.0300 seconds) + 451: 0.2989 (100000 repetitions, Perl: 0.2007 seconds, CL-PPCRE: 0.0600 seconds) + 452: 0.3008 (100000 repetitions, Perl: 0.1995 seconds, CL-PPCRE: 0.0600 seconds) + 453: 0.3715 (100000 repetitions, Perl: 0.2153 seconds, CL-PPCRE: 0.0800 seconds) + 454: 0.4187 (1000000 repetitions, Perl: 0.8120 seconds, CL-PPCRE: 0.3400 seconds) + 455: 0.7238 (100000 repetitions, Perl: 0.3039 seconds, CL-PPCRE: 0.2200 seconds) + 456: 0.7574 (100000 repetitions, Perl: 0.3301 seconds, CL-PPCRE: 0.2500 seconds) + 457: 0.9668 (100000 repetitions, Perl: 0.6309 seconds, CL-PPCRE: 0.6100 seconds) + 458: 0.3100 (100000 repetitions, Perl: 0.1290 seconds, CL-PPCRE: 0.0400 seconds) + 459: 0.3207 (100000 repetitions, Perl: 0.1247 seconds, CL-PPCRE: 0.0400 seconds) + 460: 0.3861 (100000 repetitions, Perl: 0.1295 seconds, CL-PPCRE: 0.0500 seconds) + 461: 0.3780 (100000 repetitions, Perl: 0.1323 seconds, CL-PPCRE: 0.0500 seconds) + 462: 0.3066 (100000 repetitions, Perl: 0.1305 seconds, CL-PPCRE: 0.0400 seconds) + 463: 0.3195 (100000 repetitions, Perl: 0.1252 seconds, CL-PPCRE: 0.0400 seconds) + 464: 0.4669 (100000 repetitions, Perl: 0.1285 seconds, CL-PPCRE: 0.0600 seconds) + 465: 0.4623 (100000 repetitions, Perl: 0.1298 seconds, CL-PPCRE: 0.0600 seconds) + 466: 0.4711 (100000 repetitions, Perl: 0.6580 seconds, CL-PPCRE: 0.3100 seconds) + 467: 0.3991 (100000 repetitions, Perl: 0.2756 seconds, CL-PPCRE: 0.1100 seconds) + 468: 0.4139 (100000 repetitions, Perl: 0.2657 seconds, CL-PPCRE: 0.1100 seconds) + 469: 0.5015 (100000 repetitions, Perl: 0.2193 seconds, CL-PPCRE: 0.1100 seconds) + 470: 0.4581 (100000 repetitions, Perl: 0.2183 seconds, CL-PPCRE: 0.1000 seconds) + 471: 0.3853 (100000 repetitions, Perl: 0.2336 seconds, CL-PPCRE: 0.0900 seconds) + 472: 0.5455 (100000 repetitions, Perl: 0.2200 seconds, CL-PPCRE: 0.1200 seconds) + 473: 0.5154 (100000 repetitions, Perl: 0.2522 seconds, CL-PPCRE: 0.1300 seconds) + 474: 0.6171 (100000 repetitions, Perl: 0.1945 seconds, CL-PPCRE: 0.1200 seconds) + 475: 0.3168 (100000 repetitions, Perl: 0.1578 seconds, CL-PPCRE: 0.0500 seconds) + 476: 0.5424 (100000 repetitions, Perl: 0.4241 seconds, CL-PPCRE: 0.2300 seconds) + 477: 0.4988 (100000 repetitions, Perl: 0.3007 seconds, CL-PPCRE: 0.1500 seconds) + 478: 0.6218 (100000 repetitions, Perl: 0.4342 seconds, CL-PPCRE: 0.2700 seconds) + 479: 0.5608 (100000 repetitions, Perl: 0.1605 seconds, CL-PPCRE: 0.0900 seconds) + 480: 0.5581 (100000 repetitions, Perl: 0.1792 seconds, CL-PPCRE: 0.1000 seconds) + 481: 0.5284 (100000 repetitions, Perl: 0.1514 seconds, CL-PPCRE: 0.0800 seconds) + 482: 0.5586 (100000 repetitions, Perl: 0.3222 seconds, CL-PPCRE: 0.1800 seconds) + 483: 0.4873 (100000 repetitions, Perl: 0.2052 seconds, CL-PPCRE: 0.1000 seconds) + 484: 0.5479 (100000 repetitions, Perl: 0.6388 seconds, CL-PPCRE: 0.3500 seconds) + 485: 0.5229 (100000 repetitions, Perl: 0.2869 seconds, CL-PPCRE: 0.1500 seconds) + 486: 0.5340 (100000 repetitions, Perl: 0.2247 seconds, CL-PPCRE: 0.1200 seconds) + 487: 0.3397 (100000 repetitions, Perl: 0.1766 seconds, CL-PPCRE: 0.0600 seconds) + 488: 0.4438 (100000 repetitions, Perl: 0.1803 seconds, CL-PPCRE: 0.0800 seconds) + 489: 0.5042 (100000 repetitions, Perl: 0.1983 seconds, CL-PPCRE: 0.1000 seconds) + 490: 0.2714 (100000 repetitions, Perl: 0.1474 seconds, CL-PPCRE: 0.0400 seconds) + 491: 0.2673 (100000 repetitions, Perl: 0.1497 seconds, CL-PPCRE: 0.0400 seconds) + 492: 0.3556 (1000000 repetitions, Perl: 0.7312 seconds, CL-PPCRE: 0.2600 seconds) + 493: 0.3586 (1000000 repetitions, Perl: 0.7250 seconds, CL-PPCRE: 0.2600 seconds) + 494: 0.3417 (1000000 repetitions, Perl: 0.6145 seconds, CL-PPCRE: 0.2100 seconds) + 495: 0.4060 (1000000 repetitions, Perl: 0.7390 seconds, CL-PPCRE: 0.3000 seconds) + 496: 0.3838 (1000000 repetitions, Perl: 0.7296 seconds, CL-PPCRE: 0.2800 seconds) + 497: 0.3394 (100000 repetitions, Perl: 0.1179 seconds, CL-PPCRE: 0.0400 seconds) + 498: 0.2507 (100000 repetitions, Perl: 0.1196 seconds, CL-PPCRE: 0.0300 seconds) + 499: 0.2521 (100000 repetitions, Perl: 0.1190 seconds, CL-PPCRE: 0.0300 seconds) + 500: 0.2512 (100000 repetitions, Perl: 0.1194 seconds, CL-PPCRE: 0.0300 seconds) + 501: 0.3337 (100000 repetitions, Perl: 0.1199 seconds, CL-PPCRE: 0.0400 seconds) + 502: 0.3380 (100000 repetitions, Perl: 0.1183 seconds, CL-PPCRE: 0.0400 seconds) + 503: 0.3385 (100000 repetitions, Perl: 0.1182 seconds, CL-PPCRE: 0.0400 seconds) + 504: 0.3383 (100000 repetitions, Perl: 0.1182 seconds, CL-PPCRE: 0.0400 seconds) + 505: 0.2934 (1000000 repetitions, Perl: 0.9203 seconds, CL-PPCRE: 0.2700 seconds) + 506: 0.3109 (1000000 repetitions, Perl: 0.9005 seconds, CL-PPCRE: 0.2800 seconds) + 507: 0.3253 (100000 repetitions, Perl: 0.1845 seconds, CL-PPCRE: 0.0600 seconds) + 508: 0.6707 (100000 repetitions, Perl: 0.6709 seconds, CL-PPCRE: 0.4500 seconds) + 509: 0.8568 (1000000 repetitions, Perl: 0.8753 seconds, CL-PPCRE: 0.7500 seconds) + 510: 1.0720 (100000 repetitions, Perl: 0.1119 seconds, CL-PPCRE: 0.1200 seconds) + 511: 0.3961 (100000 repetitions, Perl: 0.1262 seconds, CL-PPCRE: 0.0500 seconds) + 512: 0.3948 (100000 repetitions, Perl: 0.1266 seconds, CL-PPCRE: 0.0500 seconds) + 513: 0.3915 (100000 repetitions, Perl: 0.1277 seconds, CL-PPCRE: 0.0500 seconds) + 514: 0.5436 (100000 repetitions, Perl: 0.1288 seconds, CL-PPCRE: 0.0700 seconds) + 515: 0.5481 (100000 repetitions, Perl: 0.1277 seconds, CL-PPCRE: 0.0700 seconds) + 516: 0.4678 (100000 repetitions, Perl: 0.1283 seconds, CL-PPCRE: 0.0600 seconds) + 517: 0.5499 (100000 repetitions, Perl: 0.1273 seconds, CL-PPCRE: 0.0700 seconds) + 518: 0.6267 (100000 repetitions, Perl: 0.1277 seconds, CL-PPCRE: 0.0800 seconds) + 519: 0.5435 (100000 repetitions, Perl: 0.1288 seconds, CL-PPCRE: 0.0700 seconds) + 520: 0.5474 (100000 repetitions, Perl: 0.1279 seconds, CL-PPCRE: 0.0700 seconds) + 521: 0.6194 (100000 repetitions, Perl: 0.1292 seconds, CL-PPCRE: 0.0800 seconds) + 522: 0.6198 (100000 repetitions, Perl: 0.1291 seconds, CL-PPCRE: 0.0800 seconds) + 523: 0.5402 (100000 repetitions, Perl: 0.1296 seconds, CL-PPCRE: 0.0700 seconds) + 524: 0.5440 (100000 repetitions, Perl: 0.1287 seconds, CL-PPCRE: 0.0700 seconds) + 525: 0.6254 (100000 repetitions, Perl: 0.1279 seconds, CL-PPCRE: 0.0800 seconds) + 526: 0.6277 (100000 repetitions, Perl: 0.1274 seconds, CL-PPCRE: 0.0800 seconds) + 527: 0.5386 (100000 repetitions, Perl: 0.1300 seconds, CL-PPCRE: 0.0700 seconds) + 528: 0.5282 (100000 repetitions, Perl: 0.1325 seconds, CL-PPCRE: 0.0700 seconds) + 529: 1.0026 (1000000 repetitions, Perl: 0.7181 seconds, CL-PPCRE: 0.7200 seconds) + 530: 0.5673 (100000 repetitions, Perl: 0.1587 seconds, CL-PPCRE: 0.0900 seconds) + 531: 0.5812 (100000 repetitions, Perl: 0.1549 seconds, CL-PPCRE: 0.0900 seconds) + 532: 0.6859 (1000000 repetitions, Perl: 0.7436 seconds, CL-PPCRE: 0.5100 seconds) + 533: 0.5101 (100000 repetitions, Perl: 0.1568 seconds, CL-PPCRE: 0.0800 seconds) + 534: 0.4462 (100000 repetitions, Perl: 0.1569 seconds, CL-PPCRE: 0.0700 seconds) + 535: 0.7151 (1000000 repetitions, Perl: 0.7132 seconds, CL-PPCRE: 0.5100 seconds) + 536: 0.5707 (100000 repetitions, Perl: 0.1577 seconds, CL-PPCRE: 0.0900 seconds) + 537: 0.5677 (100000 repetitions, Perl: 0.1585 seconds, CL-PPCRE: 0.0900 seconds) + 538: 0.5097 (100000 repetitions, Perl: 0.1570 seconds, CL-PPCRE: 0.0800 seconds) + 539: 0.6915 (1000000 repetitions, Perl: 0.7375 seconds, CL-PPCRE: 0.5100 seconds) + 540: 0.5089 (100000 repetitions, Perl: 0.1572 seconds, CL-PPCRE: 0.0800 seconds) + 541: 0.5087 (100000 repetitions, Perl: 0.1573 seconds, CL-PPCRE: 0.0800 seconds) + 542: 0.4399 (100000 repetitions, Perl: 0.1591 seconds, CL-PPCRE: 0.0700 seconds) + 543: 0.4417 (100000 repetitions, Perl: 0.1585 seconds, CL-PPCRE: 0.0700 seconds) + 544: 0.8613 (100000 repetitions, Perl: 0.1741 seconds, CL-PPCRE: 0.1500 seconds) + 545: 0.4573 (100000 repetitions, Perl: 0.2843 seconds, CL-PPCRE: 0.1300 seconds) + 546: 0.7665 (100000 repetitions, Perl: 0.1827 seconds, CL-PPCRE: 0.1400 seconds) + 547: 0.5560 (100000 repetitions, Perl: 0.1439 seconds, CL-PPCRE: 0.0800 seconds) + 548: 0.5507 (100000 repetitions, Perl: 0.1453 seconds, CL-PPCRE: 0.0800 seconds) + 549: 0.6166 (100000 repetitions, Perl: 0.1946 seconds, CL-PPCRE: 0.1200 seconds) + 550: 0.2937 (100000 repetitions, Perl: 0.1362 seconds, CL-PPCRE: 0.0400 seconds) + 551: 0.3012 (100000 repetitions, Perl: 0.1328 seconds, CL-PPCRE: 0.0400 seconds) + 552: 0.2268 (100000 repetitions, Perl: 0.1323 seconds, CL-PPCRE: 0.0300 seconds) + 553: 0.6824 (100000 repetitions, Perl: 0.1905 seconds, CL-PPCRE: 0.1300 seconds) + 554: 0.2956 (100000 repetitions, Perl: 0.1353 seconds, CL-PPCRE: 0.0400 seconds) + 555: 0.2234 (100000 repetitions, Perl: 0.1343 seconds, CL-PPCRE: 0.0300 seconds) + 556: 0.2264 (100000 repetitions, Perl: 0.1325 seconds, CL-PPCRE: 0.0300 seconds) + 557: 0.6351 (100000 repetitions, Perl: 0.4409 seconds, CL-PPCRE: 0.2800 seconds) + 558: 0.5139 (100000 repetitions, Perl: 0.1751 seconds, CL-PPCRE: 0.0900 seconds) + 559: 0.6258 (100000 repetitions, Perl: 0.5274 seconds, CL-PPCRE: 0.3300 seconds) + 560: 0.6464 (100000 repetitions, Perl: 0.4487 seconds, CL-PPCRE: 0.2900 seconds) + 561: 0.5391 (100000 repetitions, Perl: 0.1855 seconds, CL-PPCRE: 0.1000 seconds) + 562: 0.6338 (100000 repetitions, Perl: 0.4576 seconds, CL-PPCRE: 0.2900 seconds) + 563: 0.4424 (100000 repetitions, Perl: 0.1582 seconds, CL-PPCRE: 0.0700 seconds) + 564: 0.4890 (100000 repetitions, Perl: 0.1840 seconds, CL-PPCRE: 0.0900 seconds) + 565: 0.6256 (100000 repetitions, Perl: 0.5435 seconds, CL-PPCRE: 0.3400 seconds) + 566: 0.4351 (100000 repetitions, Perl: 0.1609 seconds, CL-PPCRE: 0.0700 seconds) + 567: 0.4919 (100000 repetitions, Perl: 0.1830 seconds, CL-PPCRE: 0.0900 seconds) + 568: 0.6910 (100000 repetitions, Perl: 0.4631 seconds, CL-PPCRE: 0.3200 seconds) + 569: 0.4384 (100000 repetitions, Perl: 0.1597 seconds, CL-PPCRE: 0.0700 seconds) + 570: 0.4962 (100000 repetitions, Perl: 0.1814 seconds, CL-PPCRE: 0.0900 seconds) + 571: 0.6262 (100000 repetitions, Perl: 0.5429 seconds, CL-PPCRE: 0.3400 seconds) + 572: 0.3394 (100000 repetitions, Perl: 0.1473 seconds, CL-PPCRE: 0.0500 seconds) + 573: 0.3720 (100000 repetitions, Perl: 0.1613 seconds, CL-PPCRE: 0.0600 seconds) + 574: 0.5290 (100000 repetitions, Perl: 0.4915 seconds, CL-PPCRE: 0.2600 seconds) + 575: 0.5686 (100000 repetitions, Perl: 0.1055 seconds, CL-PPCRE: 0.0600 seconds) + 576: 0.2902 (100000 repetitions, Perl: 0.1378 seconds, CL-PPCRE: 0.0400 seconds) + 577: 0.3304 (100000 repetitions, Perl: 0.2421 seconds, CL-PPCRE: 0.0800 seconds) + 578: 0.3620 (100000 repetitions, Perl: 0.1381 seconds, CL-PPCRE: 0.0500 seconds) + 579: 0.3452 (100000 repetitions, Perl: 0.1448 seconds, CL-PPCRE: 0.0500 seconds) + 580: 0.2969 (100000 repetitions, Perl: 0.1684 seconds, CL-PPCRE: 0.0500 seconds) + 581: 0.4167 (100000 repetitions, Perl: 0.1440 seconds, CL-PPCRE: 0.0600 seconds) + 582: 0.4219 (100000 repetitions, Perl: 0.1422 seconds, CL-PPCRE: 0.0600 seconds) + 583: 0.4820 (100000 repetitions, Perl: 0.1452 seconds, CL-PPCRE: 0.0700 seconds) + 584: 0.2670 (100000 repetitions, Perl: 0.1498 seconds, CL-PPCRE: 0.0400 seconds) + 585: 0.2672 (100000 repetitions, Perl: 0.1497 seconds, CL-PPCRE: 0.0400 seconds) + 586: 0.8320 (100000 repetitions, Perl: 0.4207 seconds, CL-PPCRE: 0.3500 seconds) + 587: 0.3310 (100000 repetitions, Perl: 0.1208 seconds, CL-PPCRE: 0.0400 seconds) + 588: 0.3001 (1000000 repetitions, Perl: 0.8997 seconds, CL-PPCRE: 0.2700 seconds) + 589: 0.2536 (100000 repetitions, Perl: 0.1972 seconds, CL-PPCRE: 0.0500 seconds) + 590: 0.4693 (1000000 repetitions, Perl: 0.7671 seconds, CL-PPCRE: 0.3600 seconds) + 591: 0.2681 (100000 repetitions, Perl: 0.1865 seconds, CL-PPCRE: 0.0500 seconds) + 592: 0.2581 (100000 repetitions, Perl: 0.1550 seconds, CL-PPCRE: 0.0400 seconds) + 593: 0.4175 (100000 repetitions, Perl: 0.1916 seconds, CL-PPCRE: 0.0800 seconds) + 594: 0.4450 (100000 repetitions, Perl: 0.1573 seconds, CL-PPCRE: 0.0700 seconds) + 595: 0.4296 (100000 repetitions, Perl: 0.1862 seconds, CL-PPCRE: 0.0800 seconds) + 596: 0.4277 (100000 repetitions, Perl: 0.1871 seconds, CL-PPCRE: 0.0800 seconds) + 597: 0.4308 (100000 repetitions, Perl: 0.1857 seconds, CL-PPCRE: 0.0800 seconds) + 598: 0.7786 (1000000 repetitions, Perl: 0.7835 seconds, CL-PPCRE: 0.6100 seconds) + 599: 0.3235 (100000 repetitions, Perl: 0.1854 seconds, CL-PPCRE: 0.0600 seconds) + 600: 0.3302 (100000 repetitions, Perl: 0.1514 seconds, CL-PPCRE: 0.0500 seconds) + 601: 0.3100 (100000 repetitions, Perl: 0.3871 seconds, CL-PPCRE: 0.1200 seconds) + 602: 0.3929 (100000 repetitions, Perl: 0.5853 seconds, CL-PPCRE: 0.2300 seconds) + 603: 0.2478 (100000 repetitions, Perl: 0.1211 seconds, CL-PPCRE: 0.0300 seconds) + 604: 0.3026 (100000 repetitions, Perl: 0.1322 seconds, CL-PPCRE: 0.0400 seconds) + 605: 0.2324 (100000 repetitions, Perl: 0.1291 seconds, CL-PPCRE: 0.0300 seconds) + 606: 0.2566 (100000 repetitions, Perl: 0.1169 seconds, CL-PPCRE: 0.0300 seconds) + 607: 0.7426 (10000 repetitions, Perl: 0.6598 seconds, CL-PPCRE: 0.4900 seconds) + 608: 0.3101 (100000 repetitions, Perl: 0.1612 seconds, CL-PPCRE: 0.0500 seconds) + 609: 0.3097 (100000 repetitions, Perl: 0.1614 seconds, CL-PPCRE: 0.0500 seconds) + 610: 0.3080 (100000 repetitions, Perl: 0.1624 seconds, CL-PPCRE: 0.0500 seconds) + 611: 0.3044 (100000 repetitions, Perl: 0.1314 seconds, CL-PPCRE: 0.0400 seconds) + 612: 0.2972 (100000 repetitions, Perl: 0.1682 seconds, CL-PPCRE: 0.0500 seconds) + 613: 0.2979 (100000 repetitions, Perl: 0.1678 seconds, CL-PPCRE: 0.0500 seconds) + 614: 0.3004 (100000 repetitions, Perl: 0.1664 seconds, CL-PPCRE: 0.0500 seconds) + 615: 0.2998 (100000 repetitions, Perl: 0.1668 seconds, CL-PPCRE: 0.0500 seconds) + 616: 0.3094 (100000 repetitions, Perl: 0.3232 seconds, CL-PPCRE: 0.1000 seconds) + 617: 0.3499 (100000 repetitions, Perl: 0.4572 seconds, CL-PPCRE: 0.1600 seconds) + 618: 0.3665 (100000 repetitions, Perl: 0.6275 seconds, CL-PPCRE: 0.2300 seconds) + 619: 0.3663 (100000 repetitions, Perl: 0.8190 seconds, CL-PPCRE: 0.3000 seconds) + 620: 0.3761 (10000 repetitions, Perl: 0.1063 seconds, CL-PPCRE: 0.0400 seconds) + 621: 0.3691 (100000 repetitions, Perl: 0.3251 seconds, CL-PPCRE: 0.1200 seconds) + 622: 0.3314 (100000 repetitions, Perl: 0.3319 seconds, CL-PPCRE: 0.1100 seconds) + 623: 0.3612 (100000 repetitions, Perl: 0.3323 seconds, CL-PPCRE: 0.1200 seconds) + 624: 0.3560 (100000 repetitions, Perl: 0.3370 seconds, CL-PPCRE: 0.1200 seconds) + 625: 0.3616 (100000 repetitions, Perl: 0.3319 seconds, CL-PPCRE: 0.1200 seconds) + 626: 0.3517 (100000 repetitions, Perl: 0.1422 seconds, CL-PPCRE: 0.0500 seconds) + 627: 0.2692 (100000 repetitions, Perl: 0.1857 seconds, CL-PPCRE: 0.0500 seconds) + 628: 0.2865 (100000 repetitions, Perl: 0.1745 seconds, CL-PPCRE: 0.0500 seconds) + 630: 0.4441 (100000 repetitions, Perl: 0.1801 seconds, CL-PPCRE: 0.0800 seconds) + 632: 0.6037 (100000 repetitions, Perl: 0.1822 seconds, CL-PPCRE: 0.1100 seconds) + 635: 0.5615 (100000 repetitions, Perl: 0.4096 seconds, CL-PPCRE: 0.2300 seconds) + 636: 0.0000 (10 repetitions, Perl: 6.2984 seconds, CL-PPCRE: 0.0000 seconds) + 637: 0.5417 (100000 repetitions, Perl: 0.4061 seconds, CL-PPCRE: 0.2200 seconds) + 638: 0.0000 (100 repetitions, Perl: 0.1005 seconds, CL-PPCRE: 0.0000 seconds) + 639: 0.5243 (100000 repetitions, Perl: 0.1526 seconds, CL-PPCRE: 0.0800 seconds) + 640: 0.5098 (100000 repetitions, Perl: 0.1373 seconds, CL-PPCRE: 0.0700 seconds) + 641: 0.4568 (100000 repetitions, Perl: 0.2408 seconds, CL-PPCRE: 0.1100 seconds) + 642: 0.4462 (100000 repetitions, Perl: 0.2017 seconds, CL-PPCRE: 0.0900 seconds) + 643: 0.7628 (1000000 repetitions, Perl: 0.7735 seconds, CL-PPCRE: 0.5900 seconds) + 644: 0.4939 (100000 repetitions, Perl: 0.4656 seconds, CL-PPCRE: 0.2300 seconds) + 645: 0.3290 (100000 repetitions, Perl: 0.2128 seconds, CL-PPCRE: 0.0700 seconds) + 646: 0.4070 (100000 repetitions, Perl: 0.3686 seconds, CL-PPCRE: 0.1500 seconds) + 647: 0.4161 (100000 repetitions, Perl: 0.4086 seconds, CL-PPCRE: 0.1700 seconds) + 648: 0.2592 (100000 repetitions, Perl: 0.1158 seconds, CL-PPCRE: 0.0300 seconds) + 649: 0.3547 (100000 repetitions, Perl: 0.3101 seconds, CL-PPCRE: 0.1100 seconds) + 650: 0.4569 (1000000 repetitions, Perl: 0.7879 seconds, CL-PPCRE: 0.3600 seconds) + 651: 0.3252 (100000 repetitions, Perl: 0.1230 seconds, CL-PPCRE: 0.0400 seconds) + 652: 0.3773 (1000000 repetitions, Perl: 0.7950 seconds, CL-PPCRE: 0.3000 seconds) + 653: 0.3258 (100000 repetitions, Perl: 0.1228 seconds, CL-PPCRE: 0.0400 seconds) + 654: 1.4129 (1000000 repetitions, Perl: 0.8140 seconds, CL-PPCRE: 1.1500 seconds) + 655: 1.4957 (1000000 repetitions, Perl: 0.7622 seconds, CL-PPCRE: 1.1400 seconds) + 656: 0.3204 (100000 repetitions, Perl: 0.1560 seconds, CL-PPCRE: 0.0500 seconds) + 659: 0.4925 (100000 repetitions, Perl: 0.1218 seconds, CL-PPCRE: 0.0600 seconds) + 660: 0.3800 (1000000 repetitions, Perl: 0.7895 seconds, CL-PPCRE: 0.3000 seconds) + 661: 0.3298 (100000 repetitions, Perl: 0.1213 seconds, CL-PPCRE: 0.0400 seconds) + 663: 0.4117 (100000 repetitions, Perl: 0.1700 seconds, CL-PPCRE: 0.0700 seconds) + 664: 0.4841 (100000 repetitions, Perl: 0.1239 seconds, CL-PPCRE: 0.0600 seconds) + 665: 0.3108 (100000 repetitions, Perl: 0.1609 seconds, CL-PPCRE: 0.0500 seconds) + 666: 0.3096 (100000 repetitions, Perl: 0.1615 seconds, CL-PPCRE: 0.0500 seconds) + 667: 0.3054 (100000 repetitions, Perl: 0.1310 seconds, CL-PPCRE: 0.0400 seconds) + 668: 0.4166 (100000 repetitions, Perl: 0.1680 seconds, CL-PPCRE: 0.0700 seconds) + 669: 0.4020 (100000 repetitions, Perl: 0.1741 seconds, CL-PPCRE: 0.0700 seconds) + 670: 0.5613 (1000000 repetitions, Perl: 0.7660 seconds, CL-PPCRE: 0.4300 seconds) + 671: 0.3964 (100000 repetitions, Perl: 0.1513 seconds, CL-PPCRE: 0.0600 seconds) + 672: 0.5896 (1000000 repetitions, Perl: 0.7633 seconds, CL-PPCRE: 0.4500 seconds) + 673: 0.4650 (1000000 repetitions, Perl: 0.7742 seconds, CL-PPCRE: 0.3600 seconds) + 674: 0.2537 (100000 repetitions, Perl: 0.1577 seconds, CL-PPCRE: 0.0400 seconds) + 675: 0.5987 (1000000 repetitions, Perl: 0.7683 seconds, CL-PPCRE: 0.4600 seconds) + 676: 0.4043 (1000000 repetitions, Perl: 0.7667 seconds, CL-PPCRE: 0.3100 seconds) + 677: 0.3906 (1000000 repetitions, Perl: 0.7681 seconds, CL-PPCRE: 0.3000 seconds) + 678: 0.2633 (100000 repetitions, Perl: 0.1519 seconds, CL-PPCRE: 0.0400 seconds) + 679: 0.2444 (100000 repetitions, Perl: 0.1227 seconds, CL-PPCRE: 0.0300 seconds) + 680: 0.3258 (100000 repetitions, Perl: 0.1228 seconds, CL-PPCRE: 0.0400 seconds) + 681: 0.3292 (1000000 repetitions, Perl: 0.7897 seconds, CL-PPCRE: 0.2600 seconds) + 682: 0.2429 (100000 repetitions, Perl: 0.1235 seconds, CL-PPCRE: 0.0300 seconds) + 683: 0.3308 (100000 repetitions, Perl: 0.1209 seconds, CL-PPCRE: 0.0400 seconds) + 684: 0.3541 (1000000 repetitions, Perl: 0.7906 seconds, CL-PPCRE: 0.2800 seconds) + 685: 0.3376 (1000000 repetitions, Perl: 0.7996 seconds, CL-PPCRE: 0.2700 seconds) + 686: 0.3260 (100000 repetitions, Perl: 0.1227 seconds, CL-PPCRE: 0.0400 seconds) + 687: 0.2467 (100000 repetitions, Perl: 0.1216 seconds, CL-PPCRE: 0.0300 seconds) + 688: 0.3422 (1000000 repetitions, Perl: 0.7891 seconds, CL-PPCRE: 0.2700 seconds) + 689: 0.3388 (1000000 repetitions, Perl: 0.7970 seconds, CL-PPCRE: 0.2700 seconds) + 690: 0.2430 (100000 repetitions, Perl: 0.1235 seconds, CL-PPCRE: 0.0300 seconds) + 691: 0.3268 (100000 repetitions, Perl: 0.1224 seconds, CL-PPCRE: 0.0400 seconds) + 692: 0.2475 (100000 repetitions, Perl: 0.1212 seconds, CL-PPCRE: 0.0300 seconds) + 694: 0.2583 (100000 repetitions, Perl: 0.1549 seconds, CL-PPCRE: 0.0400 seconds) + 695: 0.3891 (1000000 repetitions, Perl: 0.7710 seconds, CL-PPCRE: 0.3000 seconds) + 697: 0.2431 (100000 repetitions, Perl: 0.1234 seconds, CL-PPCRE: 0.0300 seconds) + 698: 0.2484 (100000 repetitions, Perl: 0.1208 seconds, CL-PPCRE: 0.0300 seconds) + 699: 0.2462 (100000 repetitions, Perl: 0.1218 seconds, CL-PPCRE: 0.0300 seconds) + 700: 0.3274 (1000000 repetitions, Perl: 0.7941 seconds, CL-PPCRE: 0.2600 seconds) + 701: 0.3268 (100000 repetitions, Perl: 0.1224 seconds, CL-PPCRE: 0.0400 seconds) + 702: 0.2446 (100000 repetitions, Perl: 0.1226 seconds, CL-PPCRE: 0.0300 seconds) + 703: 0.2474 (100000 repetitions, Perl: 0.1212 seconds, CL-PPCRE: 0.0300 seconds) + 704: 0.3152 (1000000 repetitions, Perl: 0.7931 seconds, CL-PPCRE: 0.2500 seconds) + 705: 0.3720 (1000000 repetitions, Perl: 0.8065 seconds, CL-PPCRE: 0.3000 seconds) + 706: 0.3264 (100000 repetitions, Perl: 0.1226 seconds, CL-PPCRE: 0.0400 seconds) + 707: 0.3935 (1000000 repetitions, Perl: 0.7878 seconds, CL-PPCRE: 0.3100 seconds) + 708: 0.3254 (100000 repetitions, Perl: 0.1229 seconds, CL-PPCRE: 0.0400 seconds) + 709: 0.3775 (1000000 repetitions, Perl: 0.7948 seconds, CL-PPCRE: 0.3000 seconds) + 710: 0.3276 (100000 repetitions, Perl: 0.1221 seconds, CL-PPCRE: 0.0400 seconds) + 711: 0.2444 (100000 repetitions, Perl: 0.1228 seconds, CL-PPCRE: 0.0300 seconds) + 712: 0.2476 (100000 repetitions, Perl: 0.1212 seconds, CL-PPCRE: 0.0300 seconds) + 713: 0.3040 (1000000 repetitions, Perl: 0.7894 seconds, CL-PPCRE: 0.2400 seconds) + 715: 0.3191 (100000 repetitions, Perl: 0.1567 seconds, CL-PPCRE: 0.0500 seconds) + 716: 0.3000 (100000 repetitions, Perl: 0.1667 seconds, CL-PPCRE: 0.0500 seconds) + 717: 0.2954 (100000 repetitions, Perl: 0.1692 seconds, CL-PPCRE: 0.0500 seconds) + 718: 0.2865 (100000 repetitions, Perl: 0.1745 seconds, CL-PPCRE: 0.0500 seconds) + 719: 0.4718 (1000000 repetitions, Perl: 0.6147 seconds, CL-PPCRE: 0.2900 seconds) + 720: 0.2761 (100000 repetitions, Perl: 0.1811 seconds, CL-PPCRE: 0.0500 seconds) + 721: 0.4707 (1000000 repetitions, Perl: 0.6161 seconds, CL-PPCRE: 0.2900 seconds) + 722: 0.2801 (100000 repetitions, Perl: 0.1785 seconds, CL-PPCRE: 0.0500 seconds) + 723: 0.4566 (1000000 repetitions, Perl: 0.7885 seconds, CL-PPCRE: 0.3600 seconds) + 724: 0.4874 (1000000 repetitions, Perl: 0.6155 seconds, CL-PPCRE: 0.3000 seconds) + 725: 0.5016 (1000000 repetitions, Perl: 0.6180 seconds, CL-PPCRE: 0.3100 seconds) + 726: 0.2828 (100000 repetitions, Perl: 0.1768 seconds, CL-PPCRE: 0.0500 seconds) + 727: 0.5010 (1000000 repetitions, Perl: 0.6188 seconds, CL-PPCRE: 0.3100 seconds) + 728: 0.2833 (100000 repetitions, Perl: 0.1765 seconds, CL-PPCRE: 0.0500 seconds) + 729: 0.4384 (1000000 repetitions, Perl: 0.7756 seconds, CL-PPCRE: 0.3400 seconds) + 730: 0.5023 (1000000 repetitions, Perl: 0.6172 seconds, CL-PPCRE: 0.3100 seconds) + 731: 0.2386 (100000 repetitions, Perl: 0.1676 seconds, CL-PPCRE: 0.0400 seconds) + 732: 0.5181 (1000000 repetitions, Perl: 0.6177 seconds, CL-PPCRE: 0.3200 seconds) + 733: 0.4159 (1000000 repetitions, Perl: 0.7694 seconds, CL-PPCRE: 0.3200 seconds) + 734: 0.2543 (100000 repetitions, Perl: 0.1573 seconds, CL-PPCRE: 0.0400 seconds) + 735: 0.4703 (1000000 repetitions, Perl: 0.6166 seconds, CL-PPCRE: 0.2900 seconds) + 736: 0.2996 (100000 repetitions, Perl: 0.1669 seconds, CL-PPCRE: 0.0500 seconds) + 737: 0.4858 (1000000 repetitions, Perl: 0.6175 seconds, CL-PPCRE: 0.3000 seconds) + 738: 0.4444 (1000000 repetitions, Perl: 0.7876 seconds, CL-PPCRE: 0.3500 seconds) + 739: 0.2519 (100000 repetitions, Perl: 0.1588 seconds, CL-PPCRE: 0.0400 seconds) + 740: 0.4139 (1000000 repetitions, Perl: 0.7731 seconds, CL-PPCRE: 0.3200 seconds) + 741: 0.4308 (1000000 repetitions, Perl: 0.7660 seconds, CL-PPCRE: 0.3300 seconds) + 742: 0.4158 (1000000 repetitions, Perl: 0.7696 seconds, CL-PPCRE: 0.3200 seconds) + 743: 0.4542 (1000000 repetitions, Perl: 0.6165 seconds, CL-PPCRE: 0.2800 seconds) + 744: 0.4251 (100000 repetitions, Perl: 0.1411 seconds, CL-PPCRE: 0.0600 seconds) + 745: 0.4541 (1000000 repetitions, Perl: 0.6166 seconds, CL-PPCRE: 0.2800 seconds) + 746: 0.5009 (1000000 repetitions, Perl: 0.6189 seconds, CL-PPCRE: 0.3100 seconds) + 747: 0.6469 (1000000 repetitions, Perl: 0.7265 seconds, CL-PPCRE: 0.4700 seconds) + 748: 0.4178 (100000 repetitions, Perl: 0.1436 seconds, CL-PPCRE: 0.0600 seconds) + 749: 0.2556 (100000 repetitions, Perl: 0.1565 seconds, CL-PPCRE: 0.0400 seconds) + 750: 0.4699 (1000000 repetitions, Perl: 0.6171 seconds, CL-PPCRE: 0.2900 seconds) + 753: 0.2326 (100000 repetitions, Perl: 0.1290 seconds, CL-PPCRE: 0.0300 seconds) + 754: 0.2557 (100000 repetitions, Perl: 0.1564 seconds, CL-PPCRE: 0.0400 seconds) + 755: 0.3206 (100000 repetitions, Perl: 0.1559 seconds, CL-PPCRE: 0.0500 seconds) + 756: 0.3706 (100000 repetitions, Perl: 0.1349 seconds, CL-PPCRE: 0.0500 seconds) + 757: 0.3777 (100000 repetitions, Perl: 0.1324 seconds, CL-PPCRE: 0.0500 seconds) + 760: 0.2308 (100000 repetitions, Perl: 0.2167 seconds, CL-PPCRE: 0.0500 seconds) + 761: 0.4950 (1000000 repetitions, Perl: 0.7677 seconds, CL-PPCRE: 0.3800 seconds) + 762: 0.4656 (1000000 repetitions, Perl: 0.7731 seconds, CL-PPCRE: 0.3600 seconds) + 763: 0.2372 (100000 repetitions, Perl: 0.2108 seconds, CL-PPCRE: 0.0500 seconds) + 764: 0.4701 (1000000 repetitions, Perl: 0.7658 seconds, CL-PPCRE: 0.3600 seconds) + 765: 0.4926 (1000000 repetitions, Perl: 0.7714 seconds, CL-PPCRE: 0.3800 seconds) + 766: 0.6695 (100000 repetitions, Perl: 0.1792 seconds, CL-PPCRE: 0.1200 seconds) + 767: 1.1548 (1000000 repetitions, Perl: 0.7621 seconds, CL-PPCRE: 0.8800 seconds) + 768: 1.1199 (1000000 repetitions, Perl: 0.7679 seconds, CL-PPCRE: 0.8600 seconds) + 769: 0.3325 (100000 repetitions, Perl: 0.1804 seconds, CL-PPCRE: 0.0600 seconds) + 770: 0.5164 (1000000 repetitions, Perl: 0.7745 seconds, CL-PPCRE: 0.4000 seconds) + 771: 0.2703 (100000 repetitions, Perl: 0.1850 seconds, CL-PPCRE: 0.0500 seconds) + 772: 0.6408 (1000000 repetitions, Perl: 0.7646 seconds, CL-PPCRE: 0.4900 seconds) + 773: 0.4346 (1000000 repetitions, Perl: 0.8284 seconds, CL-PPCRE: 0.3600 seconds) + 774: 0.2671 (100000 repetitions, Perl: 0.1872 seconds, CL-PPCRE: 0.0500 seconds) + 775: 0.6119 (1000000 repetitions, Perl: 0.7681 seconds, CL-PPCRE: 0.4700 seconds) + 776: 0.4309 (1000000 repetitions, Perl: 0.8355 seconds, CL-PPCRE: 0.3600 seconds) + 777: 0.5830 (100000 repetitions, Perl: 0.1544 seconds, CL-PPCRE: 0.0900 seconds) + 778: 1.4436 (1000000 repetitions, Perl: 0.7620 seconds, CL-PPCRE: 1.1000 seconds) + 779: 0.8700 (1000000 repetitions, Perl: 0.8390 seconds, CL-PPCRE: 0.7300 seconds) + 780: 0.3165 (100000 repetitions, Perl: 0.1580 seconds, CL-PPCRE: 0.0500 seconds) + 781: 0.6059 (1000000 repetitions, Perl: 0.7756 seconds, CL-PPCRE: 0.4700 seconds) + 782: 0.4393 (1000000 repetitions, Perl: 0.8194 seconds, CL-PPCRE: 0.3600 seconds) + 783: 0.3732 (1000000 repetitions, Perl: 0.8307 seconds, CL-PPCRE: 0.3100 seconds) + 784: 0.2886 (100000 repetitions, Perl: 0.1733 seconds, CL-PPCRE: 0.0500 seconds) + 785: 0.4761 (1000000 repetitions, Perl: 0.7771 seconds, CL-PPCRE: 0.3700 seconds) + 786: 0.4285 (100000 repetitions, Perl: 0.2567 seconds, CL-PPCRE: 0.1100 seconds) + 787: 0.4003 (100000 repetitions, Perl: 0.2748 seconds, CL-PPCRE: 0.1100 seconds) + 788: 0.4010 (100000 repetitions, Perl: 0.2244 seconds, CL-PPCRE: 0.0900 seconds) + 789: 0.4943 (100000 repetitions, Perl: 0.4451 seconds, CL-PPCRE: 0.2200 seconds) + 791: 0.4275 (100000 repetitions, Perl: 0.4444 seconds, CL-PPCRE: 0.1900 seconds) + 792: 0.5687 (100000 repetitions, Perl: 0.4748 seconds, CL-PPCRE: 0.2700 seconds) + 793: 0.6169 (100000 repetitions, Perl: 0.4539 seconds, CL-PPCRE: 0.2800 seconds) + 794: 0.6400 (100000 repetitions, Perl: 0.4531 seconds, CL-PPCRE: 0.2900 seconds) + 795: 0.2678 (100000 repetitions, Perl: 0.2240 seconds, CL-PPCRE: 0.0600 seconds) + 796: 0.3119 (100000 repetitions, Perl: 0.1924 seconds, CL-PPCRE: 0.0600 seconds) + 797: 0.5787 (100000 repetitions, Perl: 0.3801 seconds, CL-PPCRE: 0.2200 seconds) + 798: 0.6085 (100000 repetitions, Perl: 0.3287 seconds, CL-PPCRE: 0.2000 seconds) + 799: 0.4050 (1000000 repetitions, Perl: 0.8149 seconds, CL-PPCRE: 0.3300 seconds) + 800: 0.3213 (100000 repetitions, Perl: 0.1556 seconds, CL-PPCRE: 0.0500 seconds) + 801: 0.2587 (100000 repetitions, Perl: 0.1546 seconds, CL-PPCRE: 0.0400 seconds) + 802: 0.3436 (100000 repetitions, Perl: 0.1455 seconds, CL-PPCRE: 0.0500 seconds) + 803: 0.4407 (100000 repetitions, Perl: 0.1361 seconds, CL-PPCRE: 0.0600 seconds) + 804: 0.6222 (1000000 repetitions, Perl: 0.7233 seconds, CL-PPCRE: 0.4500 seconds) + 805: 0.4411 (100000 repetitions, Perl: 0.1360 seconds, CL-PPCRE: 0.0600 seconds) + 806: 0.6147 (1000000 repetitions, Perl: 0.7158 seconds, CL-PPCRE: 0.4400 seconds) + 807: 0.2206 (100000 repetitions, Perl: 0.1814 seconds, CL-PPCRE: 0.0400 seconds) + 808: 0.2470 (100000 repetitions, Perl: 0.2024 seconds, CL-PPCRE: 0.0500 seconds) + 809: 0.2735 (100000 repetitions, Perl: 0.1828 seconds, CL-PPCRE: 0.0500 seconds) + 810: 0.2674 (100000 repetitions, Perl: 0.1870 seconds, CL-PPCRE: 0.0500 seconds) + 811: 0.3405 (100000 repetitions, Perl: 0.1468 seconds, CL-PPCRE: 0.0500 seconds) + 812: 0.4059 (100000 repetitions, Perl: 0.1478 seconds, CL-PPCRE: 0.0600 seconds) + 813: 0.2085 (100000 repetitions, Perl: 0.2398 seconds, CL-PPCRE: 0.0500 seconds) + 814: 0.4373 (1000000 repetitions, Perl: 0.6174 seconds, CL-PPCRE: 0.2700 seconds) + 815: 0.2669 (100000 repetitions, Perl: 0.1874 seconds, CL-PPCRE: 0.0500 seconds) + 816: 0.7040 (100000 repetitions, Perl: 0.1847 seconds, CL-PPCRE: 0.1300 seconds) + 817: 0.4656 (100000 repetitions, Perl: 0.2148 seconds, CL-PPCRE: 0.1000 seconds) + 818: 0.4928 (100000 repetitions, Perl: 0.1420 seconds, CL-PPCRE: 0.0700 seconds) + 819: 0.6155 (100000 repetitions, Perl: 0.1625 seconds, CL-PPCRE: 0.1000 seconds) + 820: 0.4187 (100000 repetitions, Perl: 0.1433 seconds, CL-PPCRE: 0.0600 seconds) + 821: 0.4519 (100000 repetitions, Perl: 0.1328 seconds, CL-PPCRE: 0.0600 seconds) + 822: 0.5520 (1000000 repetitions, Perl: 0.7970 seconds, CL-PPCRE: 0.4400 seconds) + 823: 0.6456 (1000000 repetitions, Perl: 0.7899 seconds, CL-PPCRE: 0.5100 seconds) + 824: 0.5695 (1000000 repetitions, Perl: 0.7901 seconds, CL-PPCRE: 0.4500 seconds) + 825: 5.6157 (100000 repetitions, Perl: 0.1086 seconds, CL-PPCRE: 0.6100 seconds) + 826: 0.4859 (100000 repetitions, Perl: 0.1852 seconds, CL-PPCRE: 0.0900 seconds) + 827: 0.4928 (100000 repetitions, Perl: 0.2232 seconds, CL-PPCRE: 0.1100 seconds) + 828: 0.4467 (100000 repetitions, Perl: 0.2238 seconds, CL-PPCRE: 0.1000 seconds) + 829: 0.4870 (100000 repetitions, Perl: 0.1848 seconds, CL-PPCRE: 0.0900 seconds) + 830: 0.4523 (10000 repetitions, Perl: 0.2432 seconds, CL-PPCRE: 0.1100 seconds) + 831: 0.4011 (10000 repetitions, Perl: 0.1994 seconds, CL-PPCRE: 0.0800 seconds) + 832: 0.5870 (100000 repetitions, Perl: 0.1533 seconds, CL-PPCRE: 0.0900 seconds) + 833: 0.6449 (100000 repetitions, Perl: 0.1706 seconds, CL-PPCRE: 0.1100 seconds) + 834: 0.5824 (100000 repetitions, Perl: 0.1717 seconds, CL-PPCRE: 0.1000 seconds) + 835: 0.7363 (100000 repetitions, Perl: 0.3259 seconds, CL-PPCRE: 0.2400 seconds) + 836: 0.3287 (100000 repetitions, Perl: 0.1521 seconds, CL-PPCRE: 0.0500 seconds) + 837: 0.4946 (100000 repetitions, Perl: 0.1617 seconds, CL-PPCRE: 0.0800 seconds) + 838: 0.4950 (100000 repetitions, Perl: 0.1616 seconds, CL-PPCRE: 0.0800 seconds) + 839: 0.2466 (100000 repetitions, Perl: 0.2839 seconds, CL-PPCRE: 0.0700 seconds) + 840: 0.2690 (100000 repetitions, Perl: 0.4832 seconds, CL-PPCRE: 0.1300 seconds) + 841: 0.4333 (100000 repetitions, Perl: 0.8077 seconds, CL-PPCRE: 0.3500 seconds) + 842: 0.3721 (100000 repetitions, Perl: 0.3763 seconds, CL-PPCRE: 0.1400 seconds) + 843: 0.3971 (100000 repetitions, Perl: 0.5288 seconds, CL-PPCRE: 0.2100 seconds) + 844: 0.4906 (100000 repetitions, Perl: 0.4077 seconds, CL-PPCRE: 0.2000 seconds) + 845: 0.3136 (100000 repetitions, Perl: 0.1595 seconds, CL-PPCRE: 0.0500 seconds) + 847: 0.4496 (1000000 repetitions, Perl: 0.7786 seconds, CL-PPCRE: 0.3500 seconds) + 848: 0.4622 (1000000 repetitions, Perl: 0.7789 seconds, CL-PPCRE: 0.3600 seconds) + 849: 0.4740 (100000 repetitions, Perl: 0.1899 seconds, CL-PPCRE: 0.0900 seconds) + 850: 0.8123 (1000000 repetitions, Perl: 0.8002 seconds, CL-PPCRE: 0.6500 seconds) + 851: 0.9209 (1000000 repetitions, Perl: 0.6190 seconds, CL-PPCRE: 0.5700 seconds) + 852: 0.8913 (1000000 repetitions, Perl: 0.6171 seconds, CL-PPCRE: 0.5500 seconds) + 853: 0.4788 (100000 repetitions, Perl: 0.1880 seconds, CL-PPCRE: 0.0900 seconds) + 854: 0.9083 (1000000 repetitions, Perl: 0.6165 seconds, CL-PPCRE: 0.5600 seconds) + 855: 0.5293 (100000 repetitions, Perl: 0.1700 seconds, CL-PPCRE: 0.0900 seconds) + 856: 0.5205 (100000 repetitions, Perl: 0.1729 seconds, CL-PPCRE: 0.0900 seconds) + 857: 0.4842 (100000 repetitions, Perl: 0.1446 seconds, CL-PPCRE: 0.0700 seconds) + 858: 0.4118 (100000 repetitions, Perl: 0.1457 seconds, CL-PPCRE: 0.0600 seconds) + 859: 0.8257 (1000000 repetitions, Perl: 0.7630 seconds, CL-PPCRE: 0.6300 seconds) + 860: 0.7571 (1000000 repetitions, Perl: 0.7661 seconds, CL-PPCRE: 0.5800 seconds) + 861: 0.8254 (1000000 repetitions, Perl: 0.7633 seconds, CL-PPCRE: 0.6300 seconds) + 862: 0.7463 (1000000 repetitions, Perl: 0.7637 seconds, CL-PPCRE: 0.5700 seconds) + 863: 0.3740 (100000 repetitions, Perl: 0.1604 seconds, CL-PPCRE: 0.0600 seconds) + 864: 0.3688 (100000 repetitions, Perl: 0.1627 seconds, CL-PPCRE: 0.0600 seconds) + 865: 0.4717 (1000000 repetitions, Perl: 0.7632 seconds, CL-PPCRE: 0.3600 seconds) + 866: 0.3015 (100000 repetitions, Perl: 0.1327 seconds, CL-PPCRE: 0.0400 seconds) + 867: 0.3042 (100000 repetitions, Perl: 0.1315 seconds, CL-PPCRE: 0.0400 seconds) + 868: 0.4176 (100000 repetitions, Perl: 0.1437 seconds, CL-PPCRE: 0.0600 seconds) + 869: 0.4879 (100000 repetitions, Perl: 0.1435 seconds, CL-PPCRE: 0.0700 seconds) + 870: 0.4843 (1000000 repetitions, Perl: 0.7640 seconds, CL-PPCRE: 0.3700 seconds) + 871: 0.5737 (1000000 repetitions, Perl: 0.7669 seconds, CL-PPCRE: 0.4400 seconds) + 872: 0.4173 (100000 repetitions, Perl: 0.1917 seconds, CL-PPCRE: 0.0800 seconds) + 873: 0.3683 (100000 repetitions, Perl: 0.1900 seconds, CL-PPCRE: 0.0700 seconds) + 874: 0.3494 (100000 repetitions, Perl: 0.1431 seconds, CL-PPCRE: 0.0500 seconds) + 875: 0.2311 (100000 repetitions, Perl: 0.1731 seconds, CL-PPCRE: 0.0400 seconds) + 876: 0.3566 (100000 repetitions, Perl: 0.2804 seconds, CL-PPCRE: 0.1000 seconds) + 877: 0.3548 (100000 repetitions, Perl: 0.2819 seconds, CL-PPCRE: 0.1000 seconds) + 878: 0.3539 (100000 repetitions, Perl: 0.2826 seconds, CL-PPCRE: 0.1000 seconds) + 879: 0.4957 (1000000 repetitions, Perl: 0.7666 seconds, CL-PPCRE: 0.3800 seconds) + 880: 0.6677 (100000 repetitions, Perl: 0.2396 seconds, CL-PPCRE: 0.1600 seconds) + 881: 0.3568 (100000 repetitions, Perl: 0.2803 seconds, CL-PPCRE: 0.1000 seconds) + 882: 0.3561 (100000 repetitions, Perl: 0.2808 seconds, CL-PPCRE: 0.1000 seconds) + 883: 0.3531 (100000 repetitions, Perl: 0.2832 seconds, CL-PPCRE: 0.1000 seconds) + 884: 0.4939 (1000000 repetitions, Perl: 0.7693 seconds, CL-PPCRE: 0.3800 seconds) + 885: 0.6675 (100000 repetitions, Perl: 0.2397 seconds, CL-PPCRE: 0.1600 seconds) + 886: 0.1878 (100000 repetitions, Perl: 0.2662 seconds, CL-PPCRE: 0.0500 seconds) + 887: 0.2227 (100000 repetitions, Perl: 0.2694 seconds, CL-PPCRE: 0.0600 seconds) + 888: 0.1826 (100000 repetitions, Perl: 0.2738 seconds, CL-PPCRE: 0.0500 seconds) + 889: 0.2220 (100000 repetitions, Perl: 0.1352 seconds, CL-PPCRE: 0.0300 seconds) + 890: 0.3370 (1000000 repetitions, Perl: 0.7715 seconds, CL-PPCRE: 0.2600 seconds) + 891: 0.3276 (1000000 repetitions, Perl: 0.7632 seconds, CL-PPCRE: 0.2500 seconds) + 892: 0.3100 (100000 repetitions, Perl: 0.1936 seconds, CL-PPCRE: 0.0600 seconds) + 893: 0.2601 (100000 repetitions, Perl: 0.1923 seconds, CL-PPCRE: 0.0500 seconds) + 894: 0.4041 (1000000 repetitions, Perl: 0.6187 seconds, CL-PPCRE: 0.2500 seconds) + 895: 0.3268 (1000000 repetitions, Perl: 0.7651 seconds, CL-PPCRE: 0.2500 seconds) + 896: 0.3254 (1000000 repetitions, Perl: 0.7683 seconds, CL-PPCRE: 0.2500 seconds) + 897: 0.4751 (100000 repetitions, Perl: 0.2105 seconds, CL-PPCRE: 0.1000 seconds) + 898: 0.4364 (100000 repetitions, Perl: 0.2062 seconds, CL-PPCRE: 0.0900 seconds) + 899: 0.4444 (100000 repetitions, Perl: 0.1350 seconds, CL-PPCRE: 0.0600 seconds) + 900: 0.5022 (100000 repetitions, Perl: 0.1394 seconds, CL-PPCRE: 0.0700 seconds) + 901: 0.7035 (1000000 repetitions, Perl: 0.7676 seconds, CL-PPCRE: 0.5400 seconds) + 902: 0.4586 (100000 repetitions, Perl: 0.1527 seconds, CL-PPCRE: 0.0700 seconds) + 903: 0.4671 (100000 repetitions, Perl: 0.1713 seconds, CL-PPCRE: 0.0800 seconds) + 904: 0.3907 (100000 repetitions, Perl: 0.1792 seconds, CL-PPCRE: 0.0700 seconds) + 905: 0.3864 (100000 repetitions, Perl: 0.1812 seconds, CL-PPCRE: 0.0700 seconds) + 906: 0.3806 (100000 repetitions, Perl: 0.2102 seconds, CL-PPCRE: 0.0800 seconds) + 907: 0.3776 (100000 repetitions, Perl: 0.2118 seconds, CL-PPCRE: 0.0800 seconds) + 908: 0.3921 (100000 repetitions, Perl: 0.2295 seconds, CL-PPCRE: 0.0900 seconds) + 909: 0.4301 (100000 repetitions, Perl: 0.1860 seconds, CL-PPCRE: 0.0800 seconds) + 910: 0.3195 (100000 repetitions, Perl: 0.1878 seconds, CL-PPCRE: 0.0600 seconds) + 911: 0.2436 (100000 repetitions, Perl: 0.1642 seconds, CL-PPCRE: 0.0400 seconds) + 912: 0.3041 (100000 repetitions, Perl: 0.1315 seconds, CL-PPCRE: 0.0400 seconds) + 913: 0.2414 (100000 repetitions, Perl: 0.1243 seconds, CL-PPCRE: 0.0300 seconds) + 914: 0.2742 (100000 repetitions, Perl: 0.1823 seconds, CL-PPCRE: 0.0500 seconds) + 915: 0.2971 (100000 repetitions, Perl: 0.1683 seconds, CL-PPCRE: 0.0500 seconds) + 916: 0.3023 (100000 repetitions, Perl: 0.1323 seconds, CL-PPCRE: 0.0400 seconds) + 917: 0.2352 (100000 repetitions, Perl: 0.1276 seconds, CL-PPCRE: 0.0300 seconds) + 918: 0.3308 (100000 repetitions, Perl: 0.2418 seconds, CL-PPCRE: 0.0800 seconds) + 919: 0.2534 (100000 repetitions, Perl: 0.1578 seconds, CL-PPCRE: 0.0400 seconds) + 920: 0.2807 (100000 repetitions, Perl: 0.1781 seconds, CL-PPCRE: 0.0500 seconds) + 921: 0.3005 (100000 repetitions, Perl: 0.1997 seconds, CL-PPCRE: 0.0600 seconds) + 922: 0.3028 (100000 repetitions, Perl: 0.2312 seconds, CL-PPCRE: 0.0700 seconds) + 923: 0.3821 (100000 repetitions, Perl: 0.2355 seconds, CL-PPCRE: 0.0900 seconds) + 924: 0.2499 (100000 repetitions, Perl: 0.1601 seconds, CL-PPCRE: 0.0400 seconds) + 925: 0.2759 (100000 repetitions, Perl: 0.1813 seconds, CL-PPCRE: 0.0500 seconds) + 926: 0.2996 (100000 repetitions, Perl: 0.2003 seconds, CL-PPCRE: 0.0600 seconds) + 927: 0.3238 (100000 repetitions, Perl: 0.2162 seconds, CL-PPCRE: 0.0700 seconds) + 928: 0.4485 (100000 repetitions, Perl: 0.1784 seconds, CL-PPCRE: 0.0800 seconds) + 929: 0.5143 (100000 repetitions, Perl: 0.1750 seconds, CL-PPCRE: 0.0900 seconds) + 930: 0.4808 (100000 repetitions, Perl: 0.1872 seconds, CL-PPCRE: 0.0900 seconds) + 931: 0.5237 (100000 repetitions, Perl: 0.2864 seconds, CL-PPCRE: 0.1500 seconds) + 932: 0.4539 (100000 repetitions, Perl: 0.1763 seconds, CL-PPCRE: 0.0800 seconds) + 933: 0.5025 (100000 repetitions, Perl: 0.1791 seconds, CL-PPCRE: 0.0900 seconds) + 934: 0.4820 (100000 repetitions, Perl: 0.1867 seconds, CL-PPCRE: 0.0900 seconds) + 935: 0.5277 (100000 repetitions, Perl: 0.2843 seconds, CL-PPCRE: 0.1500 seconds) + 936: 0.4468 (100000 repetitions, Perl: 0.2238 seconds, CL-PPCRE: 0.1000 seconds) + 937: 0.3800 (100000 repetitions, Perl: 0.2631 seconds, CL-PPCRE: 0.1000 seconds) + 938: 0.4090 (100000 repetitions, Perl: 0.2934 seconds, CL-PPCRE: 0.1200 seconds) + 939: 0.4672 (100000 repetitions, Perl: 0.1926 seconds, CL-PPCRE: 0.0900 seconds) + 940: 0.6314 (100000 repetitions, Perl: 0.1742 seconds, CL-PPCRE: 0.1100 seconds) + 941: 0.6664 (100000 repetitions, Perl: 0.1801 seconds, CL-PPCRE: 0.1200 seconds) + 942: 0.6355 (100000 repetitions, Perl: 0.1731 seconds, CL-PPCRE: 0.1100 seconds) + 943: 0.6240 (100000 repetitions, Perl: 0.1763 seconds, CL-PPCRE: 0.1100 seconds) + 944: 0.6861 (100000 repetitions, Perl: 0.1749 seconds, CL-PPCRE: 0.1200 seconds) + 945: 0.7400 (100000 repetitions, Perl: 0.1757 seconds, CL-PPCRE: 0.1300 seconds) + 946: 0.7302 (100000 repetitions, Perl: 0.1780 seconds, CL-PPCRE: 0.1300 seconds) + 947: 0.6298 (100000 repetitions, Perl: 0.1747 seconds, CL-PPCRE: 0.1100 seconds) + 948: 0.6705 (100000 repetitions, Perl: 0.1790 seconds, CL-PPCRE: 0.1200 seconds) + 949: 0.6259 (100000 repetitions, Perl: 0.1758 seconds, CL-PPCRE: 0.1100 seconds) + 950: 0.6232 (100000 repetitions, Perl: 0.1765 seconds, CL-PPCRE: 0.1100 seconds) + 951: 0.6639 (100000 repetitions, Perl: 0.1807 seconds, CL-PPCRE: 0.1200 seconds) + 952: 0.7448 (100000 repetitions, Perl: 0.1745 seconds, CL-PPCRE: 0.1300 seconds) + 953: 0.6846 (100000 repetitions, Perl: 0.1753 seconds, CL-PPCRE: 0.1200 seconds) + 954: 0.2594 (100000 repetitions, Perl: 0.2313 seconds, CL-PPCRE: 0.0600 seconds) + 955: 0.2587 (100000 repetitions, Perl: 0.2319 seconds, CL-PPCRE: 0.0600 seconds) + 956: 0.3055 (100000 repetitions, Perl: 0.2291 seconds, CL-PPCRE: 0.0700 seconds) + 957: 0.4766 (100000 repetitions, Perl: 0.2308 seconds, CL-PPCRE: 0.1100 seconds) + 958: 0.4771 (100000 repetitions, Perl: 0.2725 seconds, CL-PPCRE: 0.1300 seconds) + 959: 0.4772 (100000 repetitions, Perl: 0.3144 seconds, CL-PPCRE: 0.1500 seconds) + 960: 0.6517 (100000 repetitions, Perl: 0.1841 seconds, CL-PPCRE: 0.1200 seconds) + 961: 0.4511 (100000 repetitions, Perl: 0.2217 seconds, CL-PPCRE: 0.1000 seconds) + 962: 0.3977 (100000 repetitions, Perl: 0.2263 seconds, CL-PPCRE: 0.0900 seconds) + 963: 0.4044 (100000 repetitions, Perl: 0.2226 seconds, CL-PPCRE: 0.0900 seconds) + 964: 0.4084 (100000 repetitions, Perl: 0.2204 seconds, CL-PPCRE: 0.0900 seconds) + 965: 0.4408 (100000 repetitions, Perl: 0.2269 seconds, CL-PPCRE: 0.1000 seconds) + 966: 0.4340 (100000 repetitions, Perl: 0.2304 seconds, CL-PPCRE: 0.1000 seconds) + 967: 0.4000 (100000 repetitions, Perl: 0.2250 seconds, CL-PPCRE: 0.0900 seconds) + 968: 0.4063 (100000 repetitions, Perl: 0.2215 seconds, CL-PPCRE: 0.0900 seconds) + 969: 0.4449 (100000 repetitions, Perl: 0.2248 seconds, CL-PPCRE: 0.1000 seconds) + 970: 0.4263 (100000 repetitions, Perl: 0.1877 seconds, CL-PPCRE: 0.0800 seconds) + 971: 0.4445 (100000 repetitions, Perl: 0.2250 seconds, CL-PPCRE: 0.1000 seconds) + 972: 0.4297 (100000 repetitions, Perl: 0.1862 seconds, CL-PPCRE: 0.0800 seconds) + 973: 0.3937 (100000 repetitions, Perl: 0.1778 seconds, CL-PPCRE: 0.0700 seconds) + 974: 0.3974 (100000 repetitions, Perl: 0.1761 seconds, CL-PPCRE: 0.0700 seconds) + 975: 0.3941 (100000 repetitions, Perl: 0.1776 seconds, CL-PPCRE: 0.0700 seconds) + 976: 0.3917 (100000 repetitions, Perl: 0.1787 seconds, CL-PPCRE: 0.0700 seconds) + 977: 0.3929 (100000 repetitions, Perl: 0.1781 seconds, CL-PPCRE: 0.0700 seconds) + 978: 0.3915 (100000 repetitions, Perl: 0.1788 seconds, CL-PPCRE: 0.0700 seconds) + 979: 0.3970 (100000 repetitions, Perl: 0.1763 seconds, CL-PPCRE: 0.0700 seconds) + 980: 0.3956 (100000 repetitions, Perl: 0.1770 seconds, CL-PPCRE: 0.0700 seconds) + 981: 0.3936 (100000 repetitions, Perl: 0.1779 seconds, CL-PPCRE: 0.0700 seconds) + 982: 0.3955 (100000 repetitions, Perl: 0.1770 seconds, CL-PPCRE: 0.0700 seconds) + 983: 0.3928 (100000 repetitions, Perl: 0.1782 seconds, CL-PPCRE: 0.0700 seconds) + 984: 0.3968 (100000 repetitions, Perl: 0.1764 seconds, CL-PPCRE: 0.0700 seconds) + 985: 0.2590 (100000 repetitions, Perl: 0.2317 seconds, CL-PPCRE: 0.0600 seconds) + 986: 0.3023 (100000 repetitions, Perl: 0.2315 seconds, CL-PPCRE: 0.0700 seconds) + 987: 0.4364 (100000 repetitions, Perl: 0.2521 seconds, CL-PPCRE: 0.1100 seconds) + 988: 0.3976 (100000 repetitions, Perl: 0.2515 seconds, CL-PPCRE: 0.1000 seconds) + 989: 0.3863 (100000 repetitions, Perl: 0.2071 seconds, CL-PPCRE: 0.0800 seconds) + 990: 0.3864 (100000 repetitions, Perl: 0.2070 seconds, CL-PPCRE: 0.0800 seconds) + 991: 0.2795 (100000 repetitions, Perl: 0.2504 seconds, CL-PPCRE: 0.0700 seconds) + 992: 0.3350 (100000 repetitions, Perl: 0.2686 seconds, CL-PPCRE: 0.0900 seconds) + 993: 0.1875 (100000 repetitions, Perl: 0.2133 seconds, CL-PPCRE: 0.0400 seconds) + 994: 0.4958 (100000 repetitions, Perl: 0.2218 seconds, CL-PPCRE: 0.1100 seconds) + 995: 0.4927 (100000 repetitions, Perl: 0.2233 seconds, CL-PPCRE: 0.1100 seconds) + 996: 0.4889 (100000 repetitions, Perl: 0.1841 seconds, CL-PPCRE: 0.0900 seconds) + 997: 0.4658 (100000 repetitions, Perl: 0.1503 seconds, CL-PPCRE: 0.0700 seconds) + 998: 0.3414 (100000 repetitions, Perl: 0.1464 seconds, CL-PPCRE: 0.0500 seconds) + 999: 0.3149 (100000 repetitions, Perl: 0.1588 seconds, CL-PPCRE: 0.0500 seconds) +1000: 0.3993 (100000 repetitions, Perl: 0.1503 seconds, CL-PPCRE: 0.0600 seconds) +1001: 0.3749 (100000 repetitions, Perl: 0.1600 seconds, CL-PPCRE: 0.0600 seconds) +1002: 0.4008 (100000 repetitions, Perl: 0.1497 seconds, CL-PPCRE: 0.0600 seconds) +1003: 0.3744 (100000 repetitions, Perl: 0.1603 seconds, CL-PPCRE: 0.0600 seconds) +1004: 0.3792 (100000 repetitions, Perl: 0.1582 seconds, CL-PPCRE: 0.0600 seconds) +1005: 0.5061 (100000 repetitions, Perl: 0.1581 seconds, CL-PPCRE: 0.0800 seconds) +1006: 0.5539 (100000 repetitions, Perl: 0.1625 seconds, CL-PPCRE: 0.0900 seconds) +1007: 0.5210 (100000 repetitions, Perl: 0.1727 seconds, CL-PPCRE: 0.0900 seconds) +1008: 0.5835 (100000 repetitions, Perl: 0.1714 seconds, CL-PPCRE: 0.1000 seconds) +1009: 0.6770 (1000000 repetitions, Perl: 0.7681 seconds, CL-PPCRE: 0.5200 seconds) +1010: 0.6788 (1000000 repetitions, Perl: 0.7660 seconds, CL-PPCRE: 0.5200 seconds) +1011: 0.6545 (1000000 repetitions, Perl: 0.7640 seconds, CL-PPCRE: 0.5000 seconds) +1012: 0.6682 (1000000 repetitions, Perl: 0.7632 seconds, CL-PPCRE: 0.5100 seconds) +1013: 0.4885 (100000 repetitions, Perl: 0.1433 seconds, CL-PPCRE: 0.0700 seconds) +1014: 0.4995 (100000 repetitions, Perl: 0.1401 seconds, CL-PPCRE: 0.0700 seconds) +1015: 0.4964 (100000 repetitions, Perl: 0.1410 seconds, CL-PPCRE: 0.0700 seconds) +1016: 0.4570 (100000 repetitions, Perl: 0.1532 seconds, CL-PPCRE: 0.0700 seconds) +1017: 0.4607 (100000 repetitions, Perl: 0.1519 seconds, CL-PPCRE: 0.0700 seconds) +1018: 0.4578 (100000 repetitions, Perl: 0.1529 seconds, CL-PPCRE: 0.0700 seconds) +1019: 0.4573 (100000 repetitions, Perl: 0.1531 seconds, CL-PPCRE: 0.0700 seconds) +1020: 0.4685 (100000 repetitions, Perl: 0.1281 seconds, CL-PPCRE: 0.0600 seconds) +1021: 0.5708 (100000 repetitions, Perl: 0.1402 seconds, CL-PPCRE: 0.0800 seconds) +1022: 0.4815 (100000 repetitions, Perl: 0.1661 seconds, CL-PPCRE: 0.0800 seconds) +1023: 0.4868 (100000 repetitions, Perl: 0.1643 seconds, CL-PPCRE: 0.0800 seconds) +1024: 0.4939 (100000 repetitions, Perl: 0.1620 seconds, CL-PPCRE: 0.0800 seconds) +1025: 0.5472 (100000 repetitions, Perl: 0.1645 seconds, CL-PPCRE: 0.0900 seconds) +1026: 0.5505 (100000 repetitions, Perl: 0.1635 seconds, CL-PPCRE: 0.0900 seconds) +1027: 0.5315 (100000 repetitions, Perl: 0.1505 seconds, CL-PPCRE: 0.0800 seconds) +1028: 0.5022 (100000 repetitions, Perl: 0.1394 seconds, CL-PPCRE: 0.0700 seconds) +1029: 0.3264 (100000 repetitions, Perl: 0.2145 seconds, CL-PPCRE: 0.0700 seconds) +1030: 0.3346 (100000 repetitions, Perl: 0.1494 seconds, CL-PPCRE: 0.0500 seconds) +1031: 0.4008 (100000 repetitions, Perl: 0.1497 seconds, CL-PPCRE: 0.0600 seconds) +1032: 0.2813 (100000 repetitions, Perl: 0.2133 seconds, CL-PPCRE: 0.0600 seconds) +1033: 0.3560 (100000 repetitions, Perl: 0.2247 seconds, CL-PPCRE: 0.0800 seconds) +1034: 0.3124 (100000 repetitions, Perl: 0.2241 seconds, CL-PPCRE: 0.0700 seconds) +1035: 0.2817 (100000 repetitions, Perl: 0.1420 seconds, CL-PPCRE: 0.0400 seconds) +1036: 0.3732 (100000 repetitions, Perl: 0.1608 seconds, CL-PPCRE: 0.0600 seconds) +1037: 0.8908 (1000000 repetitions, Perl: 0.6174 seconds, CL-PPCRE: 0.5500 seconds) +1038: 0.8891 (1000000 repetitions, Perl: 0.6186 seconds, CL-PPCRE: 0.5500 seconds) +1039: 0.9084 (1000000 repetitions, Perl: 0.6164 seconds, CL-PPCRE: 0.5600 seconds) +1040: 0.4134 (100000 repetitions, Perl: 0.5080 seconds, CL-PPCRE: 0.2100 seconds) +1041: 0.3771 (100000 repetitions, Perl: 0.3978 seconds, CL-PPCRE: 0.1500 seconds) +1042: 0.4070 (100000 repetitions, Perl: 0.4423 seconds, CL-PPCRE: 0.1800 seconds) +1043: 0.3686 (100000 repetitions, Perl: 0.4069 seconds, CL-PPCRE: 0.1500 seconds) +1044: 0.4354 (100000 repetitions, Perl: 0.7580 seconds, CL-PPCRE: 0.3300 seconds) +1045: 0.4202 (100000 repetitions, Perl: 0.7616 seconds, CL-PPCRE: 0.3200 seconds) +1046: 0.4074 (100000 repetitions, Perl: 0.4173 seconds, CL-PPCRE: 0.1700 seconds) +1047: 0.4346 (100000 repetitions, Perl: 0.7823 seconds, CL-PPCRE: 0.3400 seconds) +1048: 0.4338 (100000 repetitions, Perl: 0.7837 seconds, CL-PPCRE: 0.3400 seconds) +1049: 0.4215 (100000 repetitions, Perl: 0.7829 seconds, CL-PPCRE: 0.3300 seconds) +1050: 0.4348 (100000 repetitions, Perl: 0.7819 seconds, CL-PPCRE: 0.3400 seconds) +1051: 0.4342 (100000 repetitions, Perl: 0.7831 seconds, CL-PPCRE: 0.3400 seconds) +1052: 0.4315 (100000 repetitions, Perl: 0.7879 seconds, CL-PPCRE: 0.3400 seconds) +1053: 1.1017 (1000000 repetitions, Perl: 0.6172 seconds, CL-PPCRE: 0.6800 seconds) +1054: 1.1006 (1000000 repetitions, Perl: 0.6179 seconds, CL-PPCRE: 0.6800 seconds) +1055: 1.1014 (1000000 repetitions, Perl: 0.6174 seconds, CL-PPCRE: 0.6800 seconds) +1056: 0.4202 (100000 repetitions, Perl: 0.4997 seconds, CL-PPCRE: 0.2100 seconds) +1057: 0.4627 (100000 repetitions, Perl: 0.3890 seconds, CL-PPCRE: 0.1800 seconds) +1058: 0.4481 (100000 repetitions, Perl: 0.4240 seconds, CL-PPCRE: 0.1900 seconds) +1059: 0.4822 (100000 repetitions, Perl: 0.3941 seconds, CL-PPCRE: 0.1900 seconds) +1060: 0.4665 (100000 repetitions, Perl: 0.6645 seconds, CL-PPCRE: 0.3100 seconds) +1061: 0.4661 (100000 repetitions, Perl: 0.6651 seconds, CL-PPCRE: 0.3100 seconds) +1062: 0.4250 (100000 repetitions, Perl: 0.4000 seconds, CL-PPCRE: 0.1700 seconds) +1063: 0.4645 (100000 repetitions, Perl: 0.6889 seconds, CL-PPCRE: 0.3200 seconds) +1064: 0.4515 (100000 repetitions, Perl: 0.6866 seconds, CL-PPCRE: 0.3100 seconds) +1065: 0.4666 (100000 repetitions, Perl: 0.6858 seconds, CL-PPCRE: 0.3200 seconds) +1066: 0.4514 (100000 repetitions, Perl: 0.6867 seconds, CL-PPCRE: 0.3100 seconds) +1067: 0.4803 (100000 repetitions, Perl: 0.6871 seconds, CL-PPCRE: 0.3300 seconds) +1068: 0.4521 (100000 repetitions, Perl: 0.6857 seconds, CL-PPCRE: 0.3100 seconds) +1069: 0.2367 (100000 repetitions, Perl: 0.1690 seconds, CL-PPCRE: 0.0400 seconds) +1070: 0.2927 (100000 repetitions, Perl: 0.1708 seconds, CL-PPCRE: 0.0500 seconds) +1071: 0.2937 (100000 repetitions, Perl: 0.1702 seconds, CL-PPCRE: 0.0500 seconds) +1072: 0.4285 (1000000 repetitions, Perl: 0.7935 seconds, CL-PPCRE: 0.3400 seconds) +1073: 0.4273 (1000000 repetitions, Perl: 0.7958 seconds, CL-PPCRE: 0.3400 seconds) +1074: 0.4155 (1000000 repetitions, Perl: 0.7702 seconds, CL-PPCRE: 0.3200 seconds) +1075: 0.3433 (100000 repetitions, Perl: 0.1456 seconds, CL-PPCRE: 0.0500 seconds) +1076: 0.3420 (100000 repetitions, Perl: 0.1462 seconds, CL-PPCRE: 0.0500 seconds) +1077: 0.4112 (100000 repetitions, Perl: 0.1459 seconds, CL-PPCRE: 0.0600 seconds) +1078: 0.4726 (100000 repetitions, Perl: 0.1481 seconds, CL-PPCRE: 0.0700 seconds) +1079: 0.2441 (100000 repetitions, Perl: 0.1229 seconds, CL-PPCRE: 0.0300 seconds) +1080: 0.3215 (100000 repetitions, Perl: 0.1244 seconds, CL-PPCRE: 0.0400 seconds) +1081: 0.4700 (100000 repetitions, Perl: 0.1489 seconds, CL-PPCRE: 0.0700 seconds) +1082: 0.4060 (100000 repetitions, Perl: 0.1478 seconds, CL-PPCRE: 0.0600 seconds) +1083: 0.6335 (1000000 repetitions, Perl: 0.6156 seconds, CL-PPCRE: 0.3900 seconds) +1084: 0.5988 (1000000 repetitions, Perl: 0.6179 seconds, CL-PPCRE: 0.3700 seconds) +1085: 0.4737 (100000 repetitions, Perl: 0.1478 seconds, CL-PPCRE: 0.0700 seconds) +1086: 0.4662 (100000 repetitions, Perl: 0.1502 seconds, CL-PPCRE: 0.0700 seconds) +1087: 0.4698 (100000 repetitions, Perl: 0.1490 seconds, CL-PPCRE: 0.0700 seconds) +1088: 0.4444 (100000 repetitions, Perl: 0.1575 seconds, CL-PPCRE: 0.0700 seconds) +1089: 0.6147 (1000000 repetitions, Perl: 0.6181 seconds, CL-PPCRE: 0.3800 seconds) +1090: 0.7628 (1000000 repetitions, Perl: 0.6162 seconds, CL-PPCRE: 0.4700 seconds) +1091: 0.4155 (100000 repetitions, Perl: 0.1444 seconds, CL-PPCRE: 0.0600 seconds) +1092: 0.3413 (100000 repetitions, Perl: 0.1465 seconds, CL-PPCRE: 0.0500 seconds) +1093: 0.3394 (100000 repetitions, Perl: 0.1473 seconds, CL-PPCRE: 0.0500 seconds) +1094: 0.4168 (100000 repetitions, Perl: 0.1439 seconds, CL-PPCRE: 0.0600 seconds) +1095: 0.4189 (100000 repetitions, Perl: 0.1432 seconds, CL-PPCRE: 0.0600 seconds) +1096: 0.4240 (100000 repetitions, Perl: 0.1415 seconds, CL-PPCRE: 0.0600 seconds) +1097: 0.6320 (1000000 repetitions, Perl: 0.7278 seconds, CL-PPCRE: 0.4600 seconds) +1098: 0.7439 (1000000 repetitions, Perl: 0.7259 seconds, CL-PPCRE: 0.5400 seconds) +1099: 0.4353 (100000 repetitions, Perl: 0.1378 seconds, CL-PPCRE: 0.0600 seconds) +1100: 0.2869 (100000 repetitions, Perl: 0.1743 seconds, CL-PPCRE: 0.0500 seconds) +1101: 0.2916 (100000 repetitions, Perl: 0.1714 seconds, CL-PPCRE: 0.0500 seconds) +1102: 0.6549 (1000000 repetitions, Perl: 0.7787 seconds, CL-PPCRE: 0.5100 seconds) +1103: 0.2606 (100000 repetitions, Perl: 0.1151 seconds, CL-PPCRE: 0.0300 seconds) +1104: 0.3060 (100000 repetitions, Perl: 0.1307 seconds, CL-PPCRE: 0.0400 seconds) +1105: 0.3699 (100000 repetitions, Perl: 0.1622 seconds, CL-PPCRE: 0.0600 seconds) +1106: 0.3107 (100000 repetitions, Perl: 0.1609 seconds, CL-PPCRE: 0.0500 seconds) +1107: 0.4186 (100000 repetitions, Perl: 0.1433 seconds, CL-PPCRE: 0.0600 seconds) +1108: 0.3705 (100000 repetitions, Perl: 0.1620 seconds, CL-PPCRE: 0.0600 seconds) +1109: 0.3070 (100000 repetitions, Perl: 0.1303 seconds, CL-PPCRE: 0.0400 seconds) +1110: 0.2271 (100000 repetitions, Perl: 0.1321 seconds, CL-PPCRE: 0.0300 seconds) +1111: 0.3084 (100000 repetitions, Perl: 0.1621 seconds, CL-PPCRE: 0.0500 seconds) +1112: 0.2849 (100000 repetitions, Perl: 0.1755 seconds, CL-PPCRE: 0.0500 seconds) +1113: 0.2561 (100000 repetitions, Perl: 0.1562 seconds, CL-PPCRE: 0.0400 seconds) +1114: 0.2522 (100000 repetitions, Perl: 0.1586 seconds, CL-PPCRE: 0.0400 seconds) +1115: 0.3156 (100000 repetitions, Perl: 0.1584 seconds, CL-PPCRE: 0.0500 seconds) +1116: 0.2411 (100000 repetitions, Perl: 0.1659 seconds, CL-PPCRE: 0.0400 seconds) +1117: 0.3145 (100000 repetitions, Perl: 0.1590 seconds, CL-PPCRE: 0.0500 seconds) +1118: 0.3867 (100000 repetitions, Perl: 0.1293 seconds, CL-PPCRE: 0.0500 seconds) +1119: 0.4624 (100000 repetitions, Perl: 0.1298 seconds, CL-PPCRE: 0.0600 seconds) +1120: 0.3085 (100000 repetitions, Perl: 0.1621 seconds, CL-PPCRE: 0.0500 seconds) +1121: 0.3127 (100000 repetitions, Perl: 0.1599 seconds, CL-PPCRE: 0.0500 seconds) +1122: 0.3696 (100000 repetitions, Perl: 0.1623 seconds, CL-PPCRE: 0.0600 seconds) +1123: 0.3817 (100000 repetitions, Perl: 0.1310 seconds, CL-PPCRE: 0.0500 seconds) +1124: 0.5259 (100000 repetitions, Perl: 0.1711 seconds, CL-PPCRE: 0.0900 seconds) +1125: 0.3481 (100000 repetitions, Perl: 0.1723 seconds, CL-PPCRE: 0.0600 seconds) +1126: 0.5827 (100000 repetitions, Perl: 0.1716 seconds, CL-PPCRE: 0.1000 seconds) +1127: 0.5218 (1000000 repetitions, Perl: 0.8432 seconds, CL-PPCRE: 0.4400 seconds) +1128: 0.5541 (100000 repetitions, Perl: 0.1444 seconds, CL-PPCRE: 0.0800 seconds) +1129: 0.4897 (1000000 repetitions, Perl: 0.9190 seconds, CL-PPCRE: 0.4500 seconds) +1130: 0.6666 (1000000 repetitions, Perl: 0.9151 seconds, CL-PPCRE: 0.6100 seconds) +1131: 0.5408 (1000000 repetitions, Perl: 0.8506 seconds, CL-PPCRE: 0.4600 seconds) +1132: 0.7029 (1000000 repetitions, Perl: 0.9105 seconds, CL-PPCRE: 0.6400 seconds) +1133: 0.3426 (100000 repetitions, Perl: 0.1751 seconds, CL-PPCRE: 0.0600 seconds) +1134: 0.4030 (100000 repetitions, Perl: 0.1737 seconds, CL-PPCRE: 0.0700 seconds) +1135: 0.3455 (100000 repetitions, Perl: 0.1737 seconds, CL-PPCRE: 0.0600 seconds) +1136: 0.2454 (100000 repetitions, Perl: 0.1223 seconds, CL-PPCRE: 0.0300 seconds) +1137: 0.3244 (100000 repetitions, Perl: 0.1233 seconds, CL-PPCRE: 0.0400 seconds) +1138: 0.2405 (100000 repetitions, Perl: 0.1247 seconds, CL-PPCRE: 0.0300 seconds) +1139: 0.3148 (1000000 repetitions, Perl: 0.7941 seconds, CL-PPCRE: 0.2500 seconds) +1140: 0.3763 (100000 repetitions, Perl: 0.1595 seconds, CL-PPCRE: 0.0600 seconds) +1141: 0.3067 (100000 repetitions, Perl: 0.1630 seconds, CL-PPCRE: 0.0500 seconds) +1142: 0.3115 (100000 repetitions, Perl: 0.1605 seconds, CL-PPCRE: 0.0500 seconds) +1143: 0.3903 (100000 repetitions, Perl: 0.1281 seconds, CL-PPCRE: 0.0500 seconds) +1144: 0.2431 (100000 repetitions, Perl: 0.1234 seconds, CL-PPCRE: 0.0300 seconds) +1145: 0.2490 (100000 repetitions, Perl: 0.1205 seconds, CL-PPCRE: 0.0300 seconds) +1146: 0.2464 (100000 repetitions, Perl: 0.1218 seconds, CL-PPCRE: 0.0300 seconds) +1147: 0.3224 (1000000 repetitions, Perl: 0.7755 seconds, CL-PPCRE: 0.2500 seconds) +1148: 0.2474 (100000 repetitions, Perl: 0.1213 seconds, CL-PPCRE: 0.0300 seconds) +1149: 0.2453 (100000 repetitions, Perl: 0.1223 seconds, CL-PPCRE: 0.0300 seconds) +1150: 0.2402 (100000 repetitions, Perl: 0.1249 seconds, CL-PPCRE: 0.0300 seconds) +1151: 0.3149 (1000000 repetitions, Perl: 0.7939 seconds, CL-PPCRE: 0.2500 seconds) +1152: 0.3758 (100000 repetitions, Perl: 0.1596 seconds, CL-PPCRE: 0.0600 seconds) +1153: 0.5027 (100000 repetitions, Perl: 0.1591 seconds, CL-PPCRE: 0.0800 seconds) +1154: 0.4940 (100000 repetitions, Perl: 0.1619 seconds, CL-PPCRE: 0.0800 seconds) +1155: 0.5548 (100000 repetitions, Perl: 0.1262 seconds, CL-PPCRE: 0.0700 seconds) +1156: 0.2429 (100000 repetitions, Perl: 0.1235 seconds, CL-PPCRE: 0.0300 seconds) +1157: 0.2446 (100000 repetitions, Perl: 0.1227 seconds, CL-PPCRE: 0.0300 seconds) +1158: 0.2415 (100000 repetitions, Perl: 0.1242 seconds, CL-PPCRE: 0.0300 seconds) +1159: 0.3301 (1000000 repetitions, Perl: 0.7877 seconds, CL-PPCRE: 0.2600 seconds) +1160: 0.2993 (100000 repetitions, Perl: 0.1336 seconds, CL-PPCRE: 0.0400 seconds) +1161: 0.3004 (100000 repetitions, Perl: 0.1332 seconds, CL-PPCRE: 0.0400 seconds) +1162: 0.4877 (100000 repetitions, Perl: 0.1640 seconds, CL-PPCRE: 0.0800 seconds) +1163: 0.2980 (100000 repetitions, Perl: 0.1678 seconds, CL-PPCRE: 0.0500 seconds) +1164: 0.3522 (100000 repetitions, Perl: 0.1419 seconds, CL-PPCRE: 0.0500 seconds) +1165: 0.3501 (100000 repetitions, Perl: 0.1428 seconds, CL-PPCRE: 0.0500 seconds) +1166: 0.4903 (1000000 repetitions, Perl: 0.6119 seconds, CL-PPCRE: 0.3000 seconds) +1167: 0.5138 (100000 repetitions, Perl: 0.1752 seconds, CL-PPCRE: 0.0900 seconds) +1168: 0.4740 (100000 repetitions, Perl: 0.1899 seconds, CL-PPCRE: 0.0900 seconds) +1169: 0.7838 (100000 repetitions, Perl: 0.1786 seconds, CL-PPCRE: 0.1400 seconds) +1170: 0.5897 (100000 repetitions, Perl: 0.2374 seconds, CL-PPCRE: 0.1400 seconds) +1171: 0.4120 (100000 repetitions, Perl: 0.1456 seconds, CL-PPCRE: 0.0600 seconds) +1172: 0.3606 (100000 repetitions, Perl: 0.3050 seconds, CL-PPCRE: 0.1100 seconds) +1173: 0.3640 (100000 repetitions, Perl: 0.3022 seconds, CL-PPCRE: 0.1100 seconds) +1174: 0.3397 (100000 repetitions, Perl: 0.2943 seconds, CL-PPCRE: 0.1000 seconds) +1175: 0.3675 (100000 repetitions, Perl: 0.2993 seconds, CL-PPCRE: 0.1100 seconds) +1176: 0.3699 (100000 repetitions, Perl: 0.1892 seconds, CL-PPCRE: 0.0700 seconds) +1177: 0.3681 (100000 repetitions, Perl: 0.1902 seconds, CL-PPCRE: 0.0700 seconds) +1178: 0.2174 (100000 repetitions, Perl: 0.1380 seconds, CL-PPCRE: 0.0300 seconds) +1179: 0.4697 (1000000 repetitions, Perl: 0.6175 seconds, CL-PPCRE: 0.2900 seconds) +1180: 0.5686 (100000 repetitions, Perl: 0.1583 seconds, CL-PPCRE: 0.0900 seconds) +1181: 0.5004 (100000 repetitions, Perl: 0.1599 seconds, CL-PPCRE: 0.0800 seconds) +1182: 0.3159 (100000 repetitions, Perl: 0.1583 seconds, CL-PPCRE: 0.0500 seconds) +1183: 0.3580 (100000 repetitions, Perl: 0.2234 seconds, CL-PPCRE: 0.0800 seconds) +1184: 0.4515 (100000 repetitions, Perl: 0.1550 seconds, CL-PPCRE: 0.0700 seconds) +1185: 0.2848 (100000 repetitions, Perl: 0.1755 seconds, CL-PPCRE: 0.0500 seconds) +1186: 0.2827 (100000 repetitions, Perl: 0.1769 seconds, CL-PPCRE: 0.0500 seconds) +1187: 0.7259 (100000 repetitions, Perl: 0.2066 seconds, CL-PPCRE: 0.1500 seconds) +1188: 0.2363 (100000 repetitions, Perl: 0.1693 seconds, CL-PPCRE: 0.0400 seconds) +1189: 0.6586 (100000 repetitions, Perl: 0.3340 seconds, CL-PPCRE: 0.2200 seconds) +1190: 0.5050 (100000 repetitions, Perl: 0.2178 seconds, CL-PPCRE: 0.1100 seconds) +1191: 0.4693 (100000 repetitions, Perl: 0.1918 seconds, CL-PPCRE: 0.0900 seconds) +1192: 0.3908 (100000 repetitions, Perl: 0.2047 seconds, CL-PPCRE: 0.0800 seconds) +1193: 0.4733 (100000 repetitions, Perl: 0.2324 seconds, CL-PPCRE: 0.1100 seconds) +1194: 0.4724 (100000 repetitions, Perl: 0.2329 seconds, CL-PPCRE: 0.1100 seconds) +1195: 0.4342 (100000 repetitions, Perl: 0.2534 seconds, CL-PPCRE: 0.1100 seconds) +1196: 0.3314 (100000 repetitions, Perl: 0.1811 seconds, CL-PPCRE: 0.0600 seconds) +1197: 0.5206 (1000000 repetitions, Perl: 0.6147 seconds, CL-PPCRE: 0.3200 seconds) +1198: 0.7281 (1000000 repetitions, Perl: 0.6180 seconds, CL-PPCRE: 0.4500 seconds) +1199: 0.5142 (100000 repetitions, Perl: 0.1556 seconds, CL-PPCRE: 0.0800 seconds) +1200: 0.5652 (100000 repetitions, Perl: 0.2123 seconds, CL-PPCRE: 0.1200 seconds) +1201: 0.8035 (100000 repetitions, Perl: 0.1494 seconds, CL-PPCRE: 0.1200 seconds) +1202: 0.4921 (100000 repetitions, Perl: 0.2439 seconds, CL-PPCRE: 0.1200 seconds) +1203: 0.5212 (100000 repetitions, Perl: 0.1727 seconds, CL-PPCRE: 0.0900 seconds) +1204: 0.5820 (100000 repetitions, Perl: 0.1890 seconds, CL-PPCRE: 0.1100 seconds) +1205: 0.5753 (100000 repetitions, Perl: 0.2260 seconds, CL-PPCRE: 0.1300 seconds) +1206: 0.5358 (100000 repetitions, Perl: 0.2986 seconds, CL-PPCRE: 0.1600 seconds) +1207: 0.5399 (100000 repetitions, Perl: 0.2963 seconds, CL-PPCRE: 0.1600 seconds) +1208: 1.0716 (100000 repetitions, Perl: 0.2053 seconds, CL-PPCRE: 0.2200 seconds) +1209: 1.1409 (100000 repetitions, Perl: 0.2104 seconds, CL-PPCRE: 0.2400 seconds) +1210: 1.1050 (100000 repetitions, Perl: 0.1991 seconds, CL-PPCRE: 0.2200 seconds) +1211: 0.4698 (1000000 repetitions, Perl: 0.6173 seconds, CL-PPCRE: 0.2900 seconds) +1212: 0.4866 (1000000 repetitions, Perl: 0.6165 seconds, CL-PPCRE: 0.3000 seconds) +1213: 0.3107 (100000 repetitions, Perl: 0.1931 seconds, CL-PPCRE: 0.0600 seconds) +1214: 0.4636 (100000 repetitions, Perl: 0.2157 seconds, CL-PPCRE: 0.1000 seconds) +1215: 0.4719 (100000 repetitions, Perl: 0.2755 seconds, CL-PPCRE: 0.1300 seconds) +1216: 0.2852 (100000 repetitions, Perl: 0.1753 seconds, CL-PPCRE: 0.0500 seconds) +1217: 0.4211 (100000 repetitions, Perl: 0.1900 seconds, CL-PPCRE: 0.0800 seconds) +1218: 0.3272 (100000 repetitions, Perl: 0.1528 seconds, CL-PPCRE: 0.0500 seconds) +1219: 0.4935 (100000 repetitions, Perl: 0.1824 seconds, CL-PPCRE: 0.0900 seconds) +1220: 0.6097 (100000 repetitions, Perl: 0.1968 seconds, CL-PPCRE: 0.1200 seconds) +1221: 0.5091 (100000 repetitions, Perl: 0.1375 seconds, CL-PPCRE: 0.0700 seconds) +1222: 0.5014 (100000 repetitions, Perl: 0.1396 seconds, CL-PPCRE: 0.0700 seconds) +1223: 0.4948 (100000 repetitions, Perl: 0.1617 seconds, CL-PPCRE: 0.0800 seconds) +1224: 0.5640 (100000 repetitions, Perl: 0.3192 seconds, CL-PPCRE: 0.1800 seconds) +1225: 0.8114 (100000 repetitions, Perl: 0.3327 seconds, CL-PPCRE: 0.2700 seconds) +1226: 0.5465 (100000 repetitions, Perl: 0.9515 seconds, CL-PPCRE: 0.5200 seconds) +1227: 0.7252 (10000 repetitions, Perl: 0.1379 seconds, CL-PPCRE: 0.1000 seconds) +1228: 0.3727 (100000 repetitions, Perl: 0.1342 seconds, CL-PPCRE: 0.0500 seconds) +1229: 0.4447 (100000 repetitions, Perl: 0.1349 seconds, CL-PPCRE: 0.0600 seconds) +1230: 0.3507 (100000 repetitions, Perl: 0.1426 seconds, CL-PPCRE: 0.0500 seconds) +1231: 0.3976 (100000 repetitions, Perl: 0.1006 seconds, CL-PPCRE: 0.0400 seconds) +1232: 0.5323 (1000000 repetitions, Perl: 0.7890 seconds, CL-PPCRE: 0.4200 seconds) +1233: 0.4362 (1000000 repetitions, Perl: 0.8253 seconds, CL-PPCRE: 0.3600 seconds) +1234: 0.4144 (1000000 repetitions, Perl: 0.8204 seconds, CL-PPCRE: 0.3400 seconds) +1235: 0.3422 (100000 repetitions, Perl: 0.1461 seconds, CL-PPCRE: 0.0500 seconds) +1236: 0.3898 (100000 repetitions, Perl: 0.1539 seconds, CL-PPCRE: 0.0600 seconds) +1237: 0.3885 (100000 repetitions, Perl: 0.1545 seconds, CL-PPCRE: 0.0600 seconds) +1238: 0.5008 (100000 repetitions, Perl: 0.1997 seconds, CL-PPCRE: 0.1000 seconds) +1239: 0.5094 (100000 repetitions, Perl: 0.1963 seconds, CL-PPCRE: 0.1000 seconds) +1240: 0.4515 (100000 repetitions, Perl: 0.1550 seconds, CL-PPCRE: 0.0700 seconds) +1241: 0.6930 (1000000 repetitions, Perl: 0.6205 seconds, CL-PPCRE: 0.4300 seconds) +1242: 0.6343 (1000000 repetitions, Perl: 0.6148 seconds, CL-PPCRE: 0.3900 seconds) +1243: 0.5096 (100000 repetitions, Perl: 0.1570 seconds, CL-PPCRE: 0.0800 seconds) +1244: 0.5477 (100000 repetitions, Perl: 0.1826 seconds, CL-PPCRE: 0.1000 seconds) +1245: 0.5955 (100000 repetitions, Perl: 0.1847 seconds, CL-PPCRE: 0.1100 seconds) +1246: 0.5025 (100000 repetitions, Perl: 0.1592 seconds, CL-PPCRE: 0.0800 seconds) +1247: 0.6442 (1000000 repetitions, Perl: 0.6209 seconds, CL-PPCRE: 0.4000 seconds) +1248: 0.8571 (1000000 repetitions, Perl: 0.6183 seconds, CL-PPCRE: 0.5300 seconds) +1249: 0.4124 (100000 repetitions, Perl: 0.1697 seconds, CL-PPCRE: 0.0700 seconds) +1250: 0.4076 (100000 repetitions, Perl: 0.1472 seconds, CL-PPCRE: 0.0600 seconds) +1251: 0.4063 (100000 repetitions, Perl: 0.1477 seconds, CL-PPCRE: 0.0600 seconds) +1252: 0.4719 (100000 repetitions, Perl: 0.1483 seconds, CL-PPCRE: 0.0700 seconds) +1253: 0.4707 (100000 repetitions, Perl: 0.1487 seconds, CL-PPCRE: 0.0700 seconds) +1254: 0.4641 (100000 repetitions, Perl: 0.1293 seconds, CL-PPCRE: 0.0600 seconds) +1255: 0.4680 (1000000 repetitions, Perl: 0.9401 seconds, CL-PPCRE: 0.4400 seconds) +1256: 0.4910 (100000 repetitions, Perl: 0.1018 seconds, CL-PPCRE: 0.0500 seconds) +1257: 0.4802 (100000 repetitions, Perl: 0.1249 seconds, CL-PPCRE: 0.0600 seconds) +1258: 0.4269 (100000 repetitions, Perl: 0.1405 seconds, CL-PPCRE: 0.0600 seconds) +1259: 0.2609 (100000 repetitions, Perl: 0.1150 seconds, CL-PPCRE: 0.0300 seconds) +1260: 0.3090 (100000 repetitions, Perl: 0.1294 seconds, CL-PPCRE: 0.0400 seconds) +1261: 0.4528 (100000 repetitions, Perl: 0.1325 seconds, CL-PPCRE: 0.0600 seconds) +1262: 0.4556 (100000 repetitions, Perl: 0.1317 seconds, CL-PPCRE: 0.0600 seconds) +1263: 0.5502 (100000 repetitions, Perl: 0.1454 seconds, CL-PPCRE: 0.0800 seconds) +1264: 0.4150 (100000 repetitions, Perl: 0.1446 seconds, CL-PPCRE: 0.0600 seconds) +1265: 0.3445 (100000 repetitions, Perl: 0.1161 seconds, CL-PPCRE: 0.0400 seconds) +1266: 0.4460 (100000 repetitions, Perl: 0.1345 seconds, CL-PPCRE: 0.0600 seconds) +1267: 0.4512 (100000 repetitions, Perl: 0.1330 seconds, CL-PPCRE: 0.0600 seconds) +1268: 0.2792 (100000 repetitions, Perl: 0.1075 seconds, CL-PPCRE: 0.0300 seconds) +1269: 0.3707 (100000 repetitions, Perl: 0.1079 seconds, CL-PPCRE: 0.0400 seconds) +1270: 0.4187 (100000 repetitions, Perl: 0.1433 seconds, CL-PPCRE: 0.0600 seconds) +1271: 0.3944 (100000 repetitions, Perl: 0.1268 seconds, CL-PPCRE: 0.0500 seconds) +1272: 0.3111 (100000 repetitions, Perl: 0.1286 seconds, CL-PPCRE: 0.0400 seconds) +1273: 0.2980 (100000 repetitions, Perl: 0.1342 seconds, CL-PPCRE: 0.0400 seconds) +1274: 0.4554 (100000 repetitions, Perl: 0.1318 seconds, CL-PPCRE: 0.0600 seconds) +1275: 0.4558 (100000 repetitions, Perl: 0.1316 seconds, CL-PPCRE: 0.0600 seconds) +1276: 0.4516 (100000 repetitions, Perl: 0.1329 seconds, CL-PPCRE: 0.0600 seconds) +1277: 0.3876 (100000 repetitions, Perl: 0.1032 seconds, CL-PPCRE: 0.0400 seconds) +1278: 0.4804 (100000 repetitions, Perl: 0.1041 seconds, CL-PPCRE: 0.0500 seconds) +1279: 0.4588 (100000 repetitions, Perl: 0.1308 seconds, CL-PPCRE: 0.0600 seconds) +1280: 0.2754 (100000 repetitions, Perl: 0.1452 seconds, CL-PPCRE: 0.0400 seconds) +1281: 0.2799 (100000 repetitions, Perl: 0.1429 seconds, CL-PPCRE: 0.0400 seconds) +1282: 0.5499 (100000 repetitions, Perl: 0.1455 seconds, CL-PPCRE: 0.0800 seconds) +1283: 0.3526 (100000 repetitions, Perl: 0.1134 seconds, CL-PPCRE: 0.0400 seconds) +1284: 0.3570 (100000 repetitions, Perl: 0.1121 seconds, CL-PPCRE: 0.0400 seconds) +1285: 0.3734 (100000 repetitions, Perl: 0.1339 seconds, CL-PPCRE: 0.0500 seconds) +1286: 0.3545 (100000 repetitions, Perl: 0.1410 seconds, CL-PPCRE: 0.0500 seconds) +1287: 0.4091 (100000 repetitions, Perl: 0.1467 seconds, CL-PPCRE: 0.0600 seconds) +1288: 0.4858 (1000000 repetitions, Perl: 0.6176 seconds, CL-PPCRE: 0.3000 seconds) +1289: 0.6510 (100000 repetitions, Perl: 0.1382 seconds, CL-PPCRE: 0.0900 seconds) +1290: 0.6770 (100000 repetitions, Perl: 0.1477 seconds, CL-PPCRE: 0.1000 seconds) +1291: 0.6942 (100000 repetitions, Perl: 0.2305 seconds, CL-PPCRE: 0.1600 seconds) +1292: 0.6907 (100000 repetitions, Perl: 0.2316 seconds, CL-PPCRE: 0.1600 seconds) +1293: 0.4198 (100000 repetitions, Perl: 0.1429 seconds, CL-PPCRE: 0.0600 seconds) +1294: 0.4822 (100000 repetitions, Perl: 0.1452 seconds, CL-PPCRE: 0.0700 seconds) +1295: 0.4146 (100000 repetitions, Perl: 0.1447 seconds, CL-PPCRE: 0.0600 seconds) +1296: 0.3391 (100000 repetitions, Perl: 0.3244 seconds, CL-PPCRE: 0.1100 seconds) +1297: 0.3420 (100000 repetitions, Perl: 0.3217 seconds, CL-PPCRE: 0.1100 seconds) +1298: 0.3516 (100000 repetitions, Perl: 0.3128 seconds, CL-PPCRE: 0.1100 seconds) +1299: 0.3490 (100000 repetitions, Perl: 0.3152 seconds, CL-PPCRE: 0.1100 seconds) +1300: 0.3570 (100000 repetitions, Perl: 0.1961 seconds, CL-PPCRE: 0.0700 seconds) +1301: 0.3511 (100000 repetitions, Perl: 0.1994 seconds, CL-PPCRE: 0.0700 seconds) +1302: 0.3363 (100000 repetitions, Perl: 0.1487 seconds, CL-PPCRE: 0.0500 seconds) +1303: 0.2163 (100000 repetitions, Perl: 0.1387 seconds, CL-PPCRE: 0.0300 seconds) +1304: 0.5458 (100000 repetitions, Perl: 0.1649 seconds, CL-PPCRE: 0.0900 seconds) +1305: 0.5308 (100000 repetitions, Perl: 0.1696 seconds, CL-PPCRE: 0.0900 seconds) +1306: 0.2966 (100000 repetitions, Perl: 0.1686 seconds, CL-PPCRE: 0.0500 seconds) +1307: 0.4821 (100000 repetitions, Perl: 0.1867 seconds, CL-PPCRE: 0.0900 seconds) +1308: 0.4939 (100000 repetitions, Perl: 0.1620 seconds, CL-PPCRE: 0.0800 seconds) +1309: 0.3487 (100000 repetitions, Perl: 0.1434 seconds, CL-PPCRE: 0.0500 seconds) +1310: 0.3636 (100000 repetitions, Perl: 0.1375 seconds, CL-PPCRE: 0.0500 seconds) +1311: 0.6696 (100000 repetitions, Perl: 0.2539 seconds, CL-PPCRE: 0.1700 seconds) +1312: 0.3703 (100000 repetitions, Perl: 0.1350 seconds, CL-PPCRE: 0.0500 seconds) +1313: 0.4320 (100000 repetitions, Perl: 0.1389 seconds, CL-PPCRE: 0.0600 seconds) +1314: 0.6490 (100000 repetitions, Perl: 0.3544 seconds, CL-PPCRE: 0.2300 seconds) +1315: 0.5671 (100000 repetitions, Perl: 0.2292 seconds, CL-PPCRE: 0.1300 seconds) +1316: 0.5198 (100000 repetitions, Perl: 0.2116 seconds, CL-PPCRE: 0.1100 seconds) +1317: 0.4623 (100000 repetitions, Perl: 0.1730 seconds, CL-PPCRE: 0.0800 seconds) +1318: 0.6373 (100000 repetitions, Perl: 0.1883 seconds, CL-PPCRE: 0.1200 seconds) +1319: 0.6446 (100000 repetitions, Perl: 0.1862 seconds, CL-PPCRE: 0.1200 seconds) +1320: 0.6559 (100000 repetitions, Perl: 0.2135 seconds, CL-PPCRE: 0.1400 seconds) +1321: 0.4390 (100000 repetitions, Perl: 0.1822 seconds, CL-PPCRE: 0.0800 seconds) +1322: 0.5881 (100000 repetitions, Perl: 0.1700 seconds, CL-PPCRE: 0.1000 seconds) +1323: 0.7739 (100000 repetitions, Perl: 0.1680 seconds, CL-PPCRE: 0.1300 seconds) +1324: 0.3400 (100000 repetitions, Perl: 0.1471 seconds, CL-PPCRE: 0.0500 seconds) +1325: 0.5080 (100000 repetitions, Perl: 0.2559 seconds, CL-PPCRE: 0.1300 seconds) +1326: 0.5332 (100000 repetitions, Perl: 0.1875 seconds, CL-PPCRE: 0.1000 seconds) +1327: 0.5438 (100000 repetitions, Perl: 0.2023 seconds, CL-PPCRE: 0.1100 seconds) +1328: 0.5896 (100000 repetitions, Perl: 0.2374 seconds, CL-PPCRE: 0.1400 seconds) +1329: 0.6437 (100000 repetitions, Perl: 0.4194 seconds, CL-PPCRE: 0.2700 seconds) +1330: 0.5475 (100000 repetitions, Perl: 0.3105 seconds, CL-PPCRE: 0.1700 seconds) +1331: 0.5626 (100000 repetitions, Perl: 0.3022 seconds, CL-PPCRE: 0.1700 seconds) +1332: 1.2478 (100000 repetitions, Perl: 0.1763 seconds, CL-PPCRE: 0.2200 seconds) +1333: 1.3674 (100000 repetitions, Perl: 0.1828 seconds, CL-PPCRE: 0.2500 seconds) +1334: 1.2733 (100000 repetitions, Perl: 0.1728 seconds, CL-PPCRE: 0.2200 seconds) +1335: 0.5285 (100000 repetitions, Perl: 0.1325 seconds, CL-PPCRE: 0.0700 seconds) +1336: 0.4142 (100000 repetitions, Perl: 0.1690 seconds, CL-PPCRE: 0.0700 seconds) +1337: 0.4689 (1000000 repetitions, Perl: 0.6185 seconds, CL-PPCRE: 0.2900 seconds) +1338: 0.4705 (1000000 repetitions, Perl: 0.6164 seconds, CL-PPCRE: 0.2900 seconds) +1339: 0.5296 (100000 repetitions, Perl: 0.1511 seconds, CL-PPCRE: 0.0800 seconds) +1340: 0.5221 (100000 repetitions, Perl: 0.1915 seconds, CL-PPCRE: 0.1000 seconds) +1341: 0.5562 (100000 repetitions, Perl: 0.2337 seconds, CL-PPCRE: 0.1300 seconds) +1342: 0.4419 (100000 repetitions, Perl: 0.1358 seconds, CL-PPCRE: 0.0600 seconds) +1343: 0.6095 (100000 repetitions, Perl: 0.1477 seconds, CL-PPCRE: 0.0900 seconds) +1344: 0.3896 (100000 repetitions, Perl: 0.1540 seconds, CL-PPCRE: 0.0600 seconds) +1345: 0.5580 (100000 repetitions, Perl: 0.1613 seconds, CL-PPCRE: 0.0900 seconds) +1346: 0.5612 (100000 repetitions, Perl: 0.1960 seconds, CL-PPCRE: 0.1100 seconds) +1347: 0.3277 (100000 repetitions, Perl: 0.2136 seconds, CL-PPCRE: 0.0700 seconds) +1348: 0.2471 (100000 repetitions, Perl: 0.2428 seconds, CL-PPCRE: 0.0600 seconds) +1349: 0.2891 (100000 repetitions, Perl: 0.2767 seconds, CL-PPCRE: 0.0800 seconds) +1350: 0.3802 (100000 repetitions, Perl: 0.2104 seconds, CL-PPCRE: 0.0800 seconds) +1351: 0.3484 (100000 repetitions, Perl: 0.2583 seconds, CL-PPCRE: 0.0900 seconds) +1352: 0.3698 (100000 repetitions, Perl: 0.2433 seconds, CL-PPCRE: 0.0900 seconds) +1353: 0.3679 (100000 repetitions, Perl: 0.2447 seconds, CL-PPCRE: 0.0900 seconds) +1354: 0.3893 (100000 repetitions, Perl: 0.3853 seconds, CL-PPCRE: 0.1500 seconds) +1355: 0.3846 (100000 repetitions, Perl: 0.2600 seconds, CL-PPCRE: 0.1000 seconds) +1356: 0.4225 (100000 repetitions, Perl: 0.3313 seconds, CL-PPCRE: 0.1400 seconds) +1357: 0.4133 (100000 repetitions, Perl: 0.3145 seconds, CL-PPCRE: 0.1300 seconds) +1358: 0.4143 (100000 repetitions, Perl: 0.3379 seconds, CL-PPCRE: 0.1400 seconds) +1359: 0.3678 (100000 repetitions, Perl: 0.3806 seconds, CL-PPCRE: 0.1400 seconds) +1360: 0.4124 (100000 repetitions, Perl: 0.3637 seconds, CL-PPCRE: 0.1500 seconds) +1361: 0.4276 (100000 repetitions, Perl: 0.3508 seconds, CL-PPCRE: 0.1500 seconds) +1362: 0.4059 (100000 repetitions, Perl: 0.3449 seconds, CL-PPCRE: 0.1400 seconds) +1363: 0.3658 (100000 repetitions, Perl: 0.3827 seconds, CL-PPCRE: 0.1400 seconds) +1364: 0.4070 (100000 repetitions, Perl: 0.3440 seconds, CL-PPCRE: 0.1400 seconds) +1365: 0.4046 (100000 repetitions, Perl: 0.2966 seconds, CL-PPCRE: 0.1200 seconds) +1366: 0.3032 (100000 repetitions, Perl: 0.2639 seconds, CL-PPCRE: 0.0800 seconds) +1367: 0.5464 (100000 repetitions, Perl: 0.1464 seconds, CL-PPCRE: 0.0800 seconds) +1368: 0.2849 (100000 repetitions, Perl: 0.1404 seconds, CL-PPCRE: 0.0400 seconds) +1369: 0.4075 (100000 repetitions, Perl: 0.4172 seconds, CL-PPCRE: 0.1700 seconds) +1370: 0.9250 (1000000 repetitions, Perl: 0.6162 seconds, CL-PPCRE: 0.5700 seconds) +1371: 0.4216 (100000 repetitions, Perl: 0.7589 seconds, CL-PPCRE: 0.3200 seconds) +1372: 0.4316 (100000 repetitions, Perl: 0.7877 seconds, CL-PPCRE: 0.3400 seconds) +1373: 0.6365 (100000 repetitions, Perl: 0.2828 seconds, CL-PPCRE: 0.1800 seconds) +1374: 0.7316 (100000 repetitions, Perl: 0.2324 seconds, CL-PPCRE: 0.1700 seconds) +1375: 0.6991 (100000 repetitions, Perl: 0.2575 seconds, CL-PPCRE: 0.1800 seconds) +1376: 0.4090 (100000 repetitions, Perl: 0.3912 seconds, CL-PPCRE: 0.1600 seconds) +1377: 0.2652 (100000 repetitions, Perl: 0.1885 seconds, CL-PPCRE: 0.0500 seconds) +1378: 0.3020 (100000 repetitions, Perl: 0.1325 seconds, CL-PPCRE: 0.0400 seconds) +1379: 0.2309 (100000 repetitions, Perl: 0.1299 seconds, CL-PPCRE: 0.0300 seconds) +1380: 0.2177 (100000 repetitions, Perl: 0.1838 seconds, CL-PPCRE: 0.0400 seconds) +1381: 0.2384 (100000 repetitions, Perl: 0.1678 seconds, CL-PPCRE: 0.0400 seconds) +1382: 0.2337 (100000 repetitions, Perl: 0.1711 seconds, CL-PPCRE: 0.0400 seconds) +1383: 0.2700 (100000 repetitions, Perl: 0.1852 seconds, CL-PPCRE: 0.0500 seconds) +1384: 0.2408 (100000 repetitions, Perl: 0.1661 seconds, CL-PPCRE: 0.0400 seconds) +1385: 0.4655 (100000 repetitions, Perl: 0.3437 seconds, CL-PPCRE: 0.1600 seconds) +1386: 0.8942 (100000 repetitions, Perl: 0.1342 seconds, CL-PPCRE: 0.1200 seconds) +1387: 0.3001 (100000 repetitions, Perl: 0.3665 seconds, CL-PPCRE: 0.1100 seconds) +1388: 0.3030 (100000 repetitions, Perl: 0.5611 seconds, CL-PPCRE: 0.1700 seconds) +1389: 0.3822 (100000 repetitions, Perl: 0.6802 seconds, CL-PPCRE: 0.2600 seconds) +1390: 0.4852 (100000 repetitions, Perl: 0.2473 seconds, CL-PPCRE: 0.1200 seconds) +1391: 0.7024 (100000 repetitions, Perl: 0.1424 seconds, CL-PPCRE: 0.1000 seconds) +1392: 0.3041 (100000 repetitions, Perl: 0.1644 seconds, CL-PPCRE: 0.0500 seconds) +1393: 0.5266 (100000 repetitions, Perl: 0.1709 seconds, CL-PPCRE: 0.0900 seconds) +1394: 0.3038 (100000 repetitions, Perl: 0.1646 seconds, CL-PPCRE: 0.0500 seconds) +1395: 0.4551 (100000 repetitions, Perl: 0.1758 seconds, CL-PPCRE: 0.0800 seconds) +1396: 0.3618 (1000000 repetitions, Perl: 0.8845 seconds, CL-PPCRE: 0.3200 seconds) +1397: 0.4574 (1000000 repetitions, Perl: 0.7651 seconds, CL-PPCRE: 0.3500 seconds) +1398: 0.3032 (100000 repetitions, Perl: 0.1649 seconds, CL-PPCRE: 0.0500 seconds) +1399: 0.4585 (100000 repetitions, Perl: 0.1745 seconds, CL-PPCRE: 0.0800 seconds) +1400: 0.3029 (100000 repetitions, Perl: 0.1651 seconds, CL-PPCRE: 0.0500 seconds) +1401: 0.4451 (100000 repetitions, Perl: 0.1797 seconds, CL-PPCRE: 0.0800 seconds) +1402: 0.4356 (1000000 repetitions, Perl: 0.7805 seconds, CL-PPCRE: 0.3400 seconds) +1403: 0.4575 (1000000 repetitions, Perl: 0.7651 seconds, CL-PPCRE: 0.3500 seconds) +1404: 0.3098 (100000 repetitions, Perl: 0.1614 seconds, CL-PPCRE: 0.0500 seconds) +1405: 0.4778 (100000 repetitions, Perl: 0.1674 seconds, CL-PPCRE: 0.0800 seconds) +1406: 0.3176 (100000 repetitions, Perl: 0.1574 seconds, CL-PPCRE: 0.0500 seconds) +1407: 0.5297 (100000 repetitions, Perl: 0.1699 seconds, CL-PPCRE: 0.0900 seconds) +1408: 0.3185 (100000 repetitions, Perl: 0.1570 seconds, CL-PPCRE: 0.0500 seconds) +1409: 0.4814 (1000000 repetitions, Perl: 0.7686 seconds, CL-PPCRE: 0.3700 seconds) +1410: 0.3147 (100000 repetitions, Perl: 0.1589 seconds, CL-PPCRE: 0.0500 seconds) +1411: 0.5297 (100000 repetitions, Perl: 0.1699 seconds, CL-PPCRE: 0.0900 seconds) +1412: 0.4106 (1000000 repetitions, Perl: 0.7793 seconds, CL-PPCRE: 0.3200 seconds) +1413: 0.4384 (1000000 repetitions, Perl: 0.7756 seconds, CL-PPCRE: 0.3400 seconds) +1414: 0.3158 (100000 repetitions, Perl: 0.1583 seconds, CL-PPCRE: 0.0500 seconds) +1415: 0.4746 (100000 repetitions, Perl: 0.1686 seconds, CL-PPCRE: 0.0800 seconds) +1416: 0.3202 (100000 repetitions, Perl: 0.1561 seconds, CL-PPCRE: 0.0500 seconds) +1417: 0.5344 (100000 repetitions, Perl: 0.1684 seconds, CL-PPCRE: 0.0900 seconds) +1418: 0.4052 (1000000 repetitions, Perl: 0.7651 seconds, CL-PPCRE: 0.3100 seconds) +1419: 0.3992 (1000000 repetitions, Perl: 0.7765 seconds, CL-PPCRE: 0.3100 seconds) +1420: 0.3187 (100000 repetitions, Perl: 0.1569 seconds, CL-PPCRE: 0.0500 seconds) +1421: 0.4692 (100000 repetitions, Perl: 0.1705 seconds, CL-PPCRE: 0.0800 seconds) +1422: 0.4313 (1000000 repetitions, Perl: 0.7652 seconds, CL-PPCRE: 0.3300 seconds) +1423: 0.4179 (1000000 repetitions, Perl: 0.7656 seconds, CL-PPCRE: 0.3200 seconds) +1424: 0.9233 (1000000 repetitions, Perl: 0.6174 seconds, CL-PPCRE: 0.5700 seconds) +1425: 0.5082 (100000 repetitions, Perl: 0.1377 seconds, CL-PPCRE: 0.0700 seconds) +1426: 0.5301 (100000 repetitions, Perl: 0.1698 seconds, CL-PPCRE: 0.0900 seconds) +1427: 0.4377 (100000 repetitions, Perl: 0.1371 seconds, CL-PPCRE: 0.0600 seconds) +1428: 0.8477 (100000 repetitions, Perl: 0.1533 seconds, CL-PPCRE: 0.1300 seconds) +1429: 0.5569 (100000 repetitions, Perl: 0.1616 seconds, CL-PPCRE: 0.0900 seconds) +1430: 0.5470 (100000 repetitions, Perl: 0.1645 seconds, CL-PPCRE: 0.0900 seconds) +1431: 0.2694 (100000 repetitions, Perl: 0.3340 seconds, CL-PPCRE: 0.0900 seconds) +1432: 0.3398 (100000 repetitions, Perl: 0.2648 seconds, CL-PPCRE: 0.0900 seconds) +1433: 0.3196 (100000 repetitions, Perl: 0.1564 seconds, CL-PPCRE: 0.0500 seconds) +1434: 0.2563 (100000 repetitions, Perl: 0.1561 seconds, CL-PPCRE: 0.0400 seconds) +1435: 0.2549 (100000 repetitions, Perl: 0.1569 seconds, CL-PPCRE: 0.0400 seconds) +1436: 0.3966 (1000000 repetitions, Perl: 0.7817 seconds, CL-PPCRE: 0.3100 seconds) +1437: 0.3186 (100000 repetitions, Perl: 0.1569 seconds, CL-PPCRE: 0.0500 seconds) +1438: 0.2879 (100000 repetitions, Perl: 0.1737 seconds, CL-PPCRE: 0.0500 seconds) +1440: 0.4261 (100000 repetitions, Perl: 0.1877 seconds, CL-PPCRE: 0.0800 seconds) +1441: 0.2673 (100000 repetitions, Perl: 0.1871 seconds, CL-PPCRE: 0.0500 seconds) +1442: 0.3109 (100000 repetitions, Perl: 0.2573 seconds, CL-PPCRE: 0.0800 seconds) +1443: 0.8570 (100000 repetitions, Perl: 0.1750 seconds, CL-PPCRE: 0.1500 seconds) +1444: 0.4761 (100000 repetitions, Perl: 0.1470 seconds, CL-PPCRE: 0.0700 seconds) +1445: 0.2776 (100000 repetitions, Perl: 0.1441 seconds, CL-PPCRE: 0.0400 seconds) +1446: 0.4592 (100000 repetitions, Perl: 0.1525 seconds, CL-PPCRE: 0.0700 seconds) +1447: 0.4758 (100000 repetitions, Perl: 0.1471 seconds, CL-PPCRE: 0.0700 seconds) +1448: 0.5301 (100000 repetitions, Perl: 0.1698 seconds, CL-PPCRE: 0.0900 seconds) +1449: 0.6724 (100000 repetitions, Perl: 0.1933 seconds, CL-PPCRE: 0.1300 seconds) +1450: 0.6677 (100000 repetitions, Perl: 0.1947 seconds, CL-PPCRE: 0.1300 seconds) +1451: 0.4503 (100000 repetitions, Perl: 0.1999 seconds, CL-PPCRE: 0.0900 seconds) +1452: 0.4078 (100000 repetitions, Perl: 0.1962 seconds, CL-PPCRE: 0.0800 seconds) +1453: 0.5974 (100000 repetitions, Perl: 0.1339 seconds, CL-PPCRE: 0.0800 seconds) +1454: 0.6096 (100000 repetitions, Perl: 0.1312 seconds, CL-PPCRE: 0.0800 seconds) +1455: 0.4783 (100000 repetitions, Perl: 0.1464 seconds, CL-PPCRE: 0.0700 seconds) +1456: 0.2228 (100000 repetitions, Perl: 0.1347 seconds, CL-PPCRE: 0.0300 seconds) +1457: 0.3958 (100000 repetitions, Perl: 0.1516 seconds, CL-PPCRE: 0.0600 seconds) +1458: 0.4623 (100000 repetitions, Perl: 0.1514 seconds, CL-PPCRE: 0.0700 seconds) +1459: 0.4619 (100000 repetitions, Perl: 0.1515 seconds, CL-PPCRE: 0.0700 seconds) +1460: 0.4710 (100000 repetitions, Perl: 0.1699 seconds, CL-PPCRE: 0.0800 seconds) +1461: 0.4722 (100000 repetitions, Perl: 0.1482 seconds, CL-PPCRE: 0.0700 seconds) +1462: 0.5930 (100000 repetitions, Perl: 0.1686 seconds, CL-PPCRE: 0.1000 seconds) +1463: 0.5698 (100000 repetitions, Perl: 0.1579 seconds, CL-PPCRE: 0.0900 seconds) +1464: 0.8227 (1000000 repetitions, Perl: 0.6199 seconds, CL-PPCRE: 0.5100 seconds) +1465: 0.5918 (100000 repetitions, Perl: 0.1352 seconds, CL-PPCRE: 0.0800 seconds) +1466: 0.7302 (100000 repetitions, Perl: 0.1370 seconds, CL-PPCRE: 0.1000 seconds) +1467: 0.3578 (100000 repetitions, Perl: 0.2795 seconds, CL-PPCRE: 0.1000 seconds) +1468: 0.3107 (100000 repetitions, Perl: 0.2574 seconds, CL-PPCRE: 0.0800 seconds) +1469: 0.3741 (100000 repetitions, Perl: 0.2139 seconds, CL-PPCRE: 0.0800 seconds) +1470: 0.4383 (100000 repetitions, Perl: 0.2281 seconds, CL-PPCRE: 0.1000 seconds) +1471: 0.1875 (100000 repetitions, Perl: 0.1600 seconds, CL-PPCRE: 0.0300 seconds) +1472: 0.1889 (100000 repetitions, Perl: 0.1588 seconds, CL-PPCRE: 0.0300 seconds) +1473: 0.2495 (100000 repetitions, Perl: 0.1603 seconds, CL-PPCRE: 0.0400 seconds) +1474: 0.2374 (100000 repetitions, Perl: 0.1685 seconds, CL-PPCRE: 0.0400 seconds) +1475: 0.5786 (100000 repetitions, Perl: 0.2420 seconds, CL-PPCRE: 0.1400 seconds) +1476: 0.3304 (100000 repetitions, Perl: 0.2724 seconds, CL-PPCRE: 0.0900 seconds) +1477: 0.4475 (100000 repetitions, Perl: 0.1788 seconds, CL-PPCRE: 0.0800 seconds) +1478: 0.6218 (100000 repetitions, Perl: 0.2412 seconds, CL-PPCRE: 0.1500 seconds) +1479: 0.5484 (100000 repetitions, Perl: 0.1459 seconds, CL-PPCRE: 0.0800 seconds) +1480: 0.6176 (100000 repetitions, Perl: 0.1457 seconds, CL-PPCRE: 0.0900 seconds) +1481: 0.5064 (100000 repetitions, Perl: 0.2567 seconds, CL-PPCRE: 0.1300 seconds) +1482: 0.9923 (100000 repetitions, Perl: 0.3023 seconds, CL-PPCRE: 0.3000 seconds) +1483: 0.4191 (100000 repetitions, Perl: 0.1909 seconds, CL-PPCRE: 0.0800 seconds) +1484: 0.4962 (100000 repetitions, Perl: 0.1814 seconds, CL-PPCRE: 0.0900 seconds) +1485: 0.5508 (100000 repetitions, Perl: 0.2542 seconds, CL-PPCRE: 0.1400 seconds) +1486: 1.0588 (100000 repetitions, Perl: 0.3022 seconds, CL-PPCRE: 0.3200 seconds) +1487: 0.7284 (100000 repetitions, Perl: 0.6453 seconds, CL-PPCRE: 0.4700 seconds) +1488: 0.7429 (100000 repetitions, Perl: 0.6461 seconds, CL-PPCRE: 0.4800 seconds) +1489: 0.4189 (100000 repetitions, Perl: 0.1910 seconds, CL-PPCRE: 0.0800 seconds) +1490: 0.3235 (100000 repetitions, Perl: 0.1546 seconds, CL-PPCRE: 0.0500 seconds) +1491: 0.5143 (100000 repetitions, Perl: 0.1556 seconds, CL-PPCRE: 0.0800 seconds) +1492: 0.4563 (100000 repetitions, Perl: 0.1534 seconds, CL-PPCRE: 0.0700 seconds) +1493: 0.5185 (100000 repetitions, Perl: 0.1543 seconds, CL-PPCRE: 0.0800 seconds) +1494: 0.4955 (100000 repetitions, Perl: 0.1615 seconds, CL-PPCRE: 0.0800 seconds) +1495: 0.4944 (100000 repetitions, Perl: 0.1618 seconds, CL-PPCRE: 0.0800 seconds) +1496: 0.4331 (100000 repetitions, Perl: 0.8082 seconds, CL-PPCRE: 0.3500 seconds) +1497: 0.7886 (1000000 repetitions, Perl: 0.7608 seconds, CL-PPCRE: 0.6000 seconds) +1498: 0.5902 (1000000 repetitions, Perl: 0.7624 seconds, CL-PPCRE: 0.4500 seconds) +1499: 0.2554 (100000 repetitions, Perl: 0.1566 seconds, CL-PPCRE: 0.0400 seconds) +1500: 0.2541 (100000 repetitions, Perl: 0.1574 seconds, CL-PPCRE: 0.0400 seconds) +1501: 0.2524 (100000 repetitions, Perl: 0.1585 seconds, CL-PPCRE: 0.0400 seconds) +1502: 0.3265 (100000 repetitions, Perl: 0.3369 seconds, CL-PPCRE: 0.1100 seconds) +1503: 0.3811 (100000 repetitions, Perl: 0.3674 seconds, CL-PPCRE: 0.1400 seconds) +1504: 0.3815 (100000 repetitions, Perl: 0.3670 seconds, CL-PPCRE: 0.1400 seconds) +1505: 0.3818 (100000 repetitions, Perl: 0.3667 seconds, CL-PPCRE: 0.1400 seconds) +1506: 0.4213 (100000 repetitions, Perl: 0.4510 seconds, CL-PPCRE: 0.1900 seconds) +1507: 0.4781 (100000 repetitions, Perl: 0.5438 seconds, CL-PPCRE: 0.2600 seconds) +1508: 0.6455 (100000 repetitions, Perl: 0.6972 seconds, CL-PPCRE: 0.4500 seconds) +1509: 0.5764 (100000 repetitions, Perl: 0.5899 seconds, CL-PPCRE: 0.3400 seconds) +1510: 0.5361 (100000 repetitions, Perl: 0.4850 seconds, CL-PPCRE: 0.2600 seconds) +1511: 0.7082 (1000000 repetitions, Perl: 0.6495 seconds, CL-PPCRE: 0.4600 seconds) +1512: 0.5625 (100000 repetitions, Perl: 0.1600 seconds, CL-PPCRE: 0.0900 seconds) +1513: 0.5700 (100000 repetitions, Perl: 0.1579 seconds, CL-PPCRE: 0.0900 seconds) +1514: 0.5287 (100000 repetitions, Perl: 0.2837 seconds, CL-PPCRE: 0.1500 seconds) +1515: 0.5201 (100000 repetitions, Perl: 0.2884 seconds, CL-PPCRE: 0.1500 seconds) +1516: 0.5035 (100000 repetitions, Perl: 0.2780 seconds, CL-PPCRE: 0.1400 seconds) +1517: 0.5849 (100000 repetitions, Perl: 0.2906 seconds, CL-PPCRE: 0.1700 seconds) +1518: 0.6021 (100000 repetitions, Perl: 0.2824 seconds, CL-PPCRE: 0.1700 seconds) +1519: 0.6077 (100000 repetitions, Perl: 0.3127 seconds, CL-PPCRE: 0.1900 seconds) +1520: 0.7115 (100000 repetitions, Perl: 0.6746 seconds, CL-PPCRE: 0.4800 seconds) +1521: 0.7063 (100000 repetitions, Perl: 0.6796 seconds, CL-PPCRE: 0.4800 seconds) +1522: 0.7059 (100000 repetitions, Perl: 0.6658 seconds, CL-PPCRE: 0.4700 seconds) +1523: 0.7191 (100000 repetitions, Perl: 0.6675 seconds, CL-PPCRE: 0.4800 seconds) +1524: 0.4683 (100000 repetitions, Perl: 0.1922 seconds, CL-PPCRE: 0.0900 seconds) +1525: 0.4213 (100000 repetitions, Perl: 0.2136 seconds, CL-PPCRE: 0.0900 seconds) +1526: 0.0286 (10000 repetitions, Perl: 0.3498 seconds, CL-PPCRE: 0.0100 seconds) +1527: 0.6763 (100000 repetitions, Perl: 0.8429 seconds, CL-PPCRE: 0.5700 seconds) +1528: 0.8554 (1000000 repetitions, Perl: 0.8768 seconds, CL-PPCRE: 0.7500 seconds) +1529: 0.9597 (100000 repetitions, Perl: 0.1146 seconds, CL-PPCRE: 0.1100 seconds) +1530: 0.2910 (100000 repetitions, Perl: 0.2406 seconds, CL-PPCRE: 0.0700 seconds) +1531: 0.2867 (100000 repetitions, Perl: 0.2442 seconds, CL-PPCRE: 0.0700 seconds) +1532: 0.3131 (100000 repetitions, Perl: 0.1597 seconds, CL-PPCRE: 0.0500 seconds) +1533: 0.3589 (100000 repetitions, Perl: 0.2508 seconds, CL-PPCRE: 0.0900 seconds) +1534: 0.3536 (100000 repetitions, Perl: 0.2546 seconds, CL-PPCRE: 0.0900 seconds) +1535: 0.3596 (100000 repetitions, Perl: 0.1947 seconds, CL-PPCRE: 0.0700 seconds) +1536: 0.3210 (100000 repetitions, Perl: 0.2492 seconds, CL-PPCRE: 0.0800 seconds) +1537: 0.2765 (100000 repetitions, Perl: 0.2531 seconds, CL-PPCRE: 0.0700 seconds) +1538: 0.3216 (100000 repetitions, Perl: 0.1866 seconds, CL-PPCRE: 0.0600 seconds) +1539: 0.3169 (100000 repetitions, Perl: 0.2524 seconds, CL-PPCRE: 0.0800 seconds) +1540: 0.3192 (100000 repetitions, Perl: 0.2506 seconds, CL-PPCRE: 0.0800 seconds) +1541: 0.3373 (100000 repetitions, Perl: 0.2075 seconds, CL-PPCRE: 0.0700 seconds) +1542: 0.7186 (100000 repetitions, Perl: 0.2644 seconds, CL-PPCRE: 0.1900 seconds) +1543: 0.7809 (100000 repetitions, Perl: 0.4354 seconds, CL-PPCRE: 0.3400 seconds) +1544: 0.7975 (100000 repetitions, Perl: 0.4389 seconds, CL-PPCRE: 0.3500 seconds) +1545: 0.7251 (100000 repetitions, Perl: 0.2620 seconds, CL-PPCRE: 0.1900 seconds) +1546: 0.7521 (100000 repetitions, Perl: 0.4387 seconds, CL-PPCRE: 0.3300 seconds) +1547: 0.8778 (100000 repetitions, Perl: 0.4443 seconds, CL-PPCRE: 0.3900 seconds) +1548: 0.5969 (100000 repetitions, Perl: 0.3016 seconds, CL-PPCRE: 0.1800 seconds) +1549: 0.7601 (100000 repetitions, Perl: 0.4736 seconds, CL-PPCRE: 0.3600 seconds) +1550: 0.7864 (100000 repetitions, Perl: 0.4832 seconds, CL-PPCRE: 0.3800 seconds) +1551: 0.5106 (100000 repetitions, Perl: 0.3330 seconds, CL-PPCRE: 0.1700 seconds) +1552: 0.4608 (100000 repetitions, Perl: 0.3038 seconds, CL-PPCRE: 0.1400 seconds) +1553: 0.4988 (100000 repetitions, Perl: 0.3207 seconds, CL-PPCRE: 0.1600 seconds) +1554: 0.3418 (100000 repetitions, Perl: 0.3803 seconds, CL-PPCRE: 0.1300 seconds) +1555: 0.3461 (100000 repetitions, Perl: 0.2311 seconds, CL-PPCRE: 0.0800 seconds) +1556: 0.2425 (100000 repetitions, Perl: 0.1237 seconds, CL-PPCRE: 0.0300 seconds) +1557: 0.3378 (100000 repetitions, Perl: 0.1184 seconds, CL-PPCRE: 0.0400 seconds) +1558: 0.3310 (100000 repetitions, Perl: 0.1208 seconds, CL-PPCRE: 0.0400 seconds) +1559: 0.3415 (100000 repetitions, Perl: 0.1171 seconds, CL-PPCRE: 0.0400 seconds) +1560: 0.3131 (1000000 repetitions, Perl: 0.8943 seconds, CL-PPCRE: 0.2800 seconds) +1561: 0.3385 (100000 repetitions, Perl: 0.1182 seconds, CL-PPCRE: 0.0400 seconds) +1562: 0.2542 (100000 repetitions, Perl: 0.1180 seconds, CL-PPCRE: 0.0300 seconds) +1563: 0.2498 (100000 repetitions, Perl: 0.1201 seconds, CL-PPCRE: 0.0300 seconds) +1564: 0.3125 (1000000 repetitions, Perl: 0.8961 seconds, CL-PPCRE: 0.2800 seconds) \ No newline at end of file diff --git a/practicals/libraries/cl-ppcre-1.2.3/doc/index.html b/practicals/libraries/cl-ppcre-1.2.3/doc/index.html new file mode 100644 index 0000000..ea2b42d --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/doc/index.html @@ -0,0 +1,2318 @@ + + + + + + CL-PPCRE - portable Perl-compatible regular expressions for Common Lisp + + + + + +

CL-PPCRE - portable Perl-compatible regular expressions for Common Lisp

+ +
+
 

Abstract

+ +CL-PPCRE is a portable regular expression library for Common Lisp +which has the following features: + +
+ +CL-PPCRE has been used successfully in various applications like BioLingua, LoGS, or The Regex Coach. + +

+Download shortcut: http://weitz.de/files/cl-ppcre.tar.gz. + +

+ +
 

Contents

+
    +
  1. Download and installation +
  2. Support and mailing lists +
  3. The CL-PPCRE dictionary +
      +
    1. create-scanner (for Perl regex strings) +
    2. create-scanner (for parse trees) +
    3. parse-tree-synonym +
    4. define-parse-tree-synonym +
    5. scan +
    6. scan-to-strings +
    7. register-groups-bind +
    8. do-scans +
    9. do-matches +
    10. do-matches-as-strings +
    11. do-register-groups +
    12. all-matches +
    13. all-matches-as-strings +
    14. split +
    15. regex-replace +
    16. regex-replace-all +
    17. regex-apropos +
    18. regex-apropos-list +
    19. *regex-char-code-limit* +
    20. *use-bmh-matchers* +
    21. *allow-quoting* +
    22. quote-meta-chars +
    23. ppcre-error +
    24. ppcre-invocation-error +
    25. ppcre-syntax-error +
    26. ppcre-syntax-error-string +
    27. ppcre-syntax-error-pos +
    +
  4. Filters +
  5. Testing CL-PPCRE +
  6. Compatibility with Perl +
      +
    1. Empty strings instead of undef in $1, $2, etc. +
    2. Strange scoping of embedded modifiers +
    3. Inconsistent capturing of $1, $2, etc. +
    4. Captured groups not available outside of look-aheads and look-behinds +
    5. Alternations don't always work from left to right +
    6. "\r" doesn't work with MCL +
    7. What about "\w"? +
    +
  7. Performance +
      +
    1. Benchmarking +
    2. Other performance issues +
    +
  8. Bugs and problems +
      +
    1. Stack overflow +
    2. "\Q" doesn't work, or does it? +
    3. Backslashes may confuse you... +
    +
  9. Remarks +
  10. AllegroCL compatibility mode +
  11. Acknowledgements +
+ +
 

Download and installation

+ +CL-PPCRE together with this documentation can be downloaded from http://weitz.de/files/cl-ppcre.tar.gz. The +current version is 1.2.3 - older versions are +available for download through URLs like +http://weitz.de/files/cl-ppcre-<version>.tar.gz (or ending in .tgz for 0.9.0 and older.). A CHANGELOG is available. +

+If you're on Debian you should +probably use the cl-ppcre +Debian package which is available thanks to Kevin +Rosenberg. There's also a port +for Gentoo Linux thanks to Matthew Kennedy and a FreeBSD port thanks to Henrik Motakef. +Installation via asdf-install should as well +be possible. +

+CL-PPCRE comes with simple system definitions for MK:DEFSYSTEM and asdf so you can either adapt it +to your needs or just unpack the archive and from within the CL-PPCRE +directory start your Lisp image and evaluate the form +(mk:compile-system "cl-ppcre") (or the +equivalent one for asdf) which should compile and load the whole +system. +

+If for some reason you don't want to use MK:DEFSYSTEM or asdf you +can just LOAD the file load.lisp or you +can also get away with something like this: + +

+(loop for name in '("packages" "specials" "util" "errors" "lexer"
+                    "parser" "regex-class" "convert" "optimize"
+                    "closures" "repetition-closures" "scanner" "api")
+      do (compile-file (make-pathname :name name
+                                      :type "lisp"))
+         (load name))
+
+ +Note that on CL implementations which use the Python compiler +(i.e. CMUCL, SBCL, SCL) you can concatenate the compiled object files +to create one single object file which you can load afterwards: + +
+cat {packages,specials,util,errors,lexer,parser,regex-class,convert,optimize,closures,repetition-closures,scanner,api}.x86f > cl-ppcre.x86f
+
+ +(Replace ".x86f" with the correct suffix for +your platform.) +

+Note that there is no public CVS repository for CL-PPCRE - the repository at common-lisp.net is out of date and not in sync with the (current) version distributed from weitz.de. + + +
 

Support and mailing lists

+ +For questions, bug reports, feature requests, improvements, or patches +please use the cl-ppcre-devel +mailing list. If you want to be notified about future releases +subscribe to the cl-ppcre-announce +mailing list. These mailing lists were made available thanks to +the services of common-lisp.net. + +
 

The CL-PPCRE dictionary

+ +CL-PPCRE exports the following symbols: + +


[Method] +
create-scanner (string string)&key case-insensitive-mode multi-line-mode single-line-mode extended-mode destructive => scanner + +


Accepts a string which is a regular expression in +Perl syntax and returns a closure which will scan strings for this +regular expression. The mode keyboard arguments are equivalent to the +"imsx" modifiers in Perl. The +destructive keyword will be ignored. +

+The function accepts most of the regex syntax of Perl 5 as described +in man +perlre including extended features like non-greedy +repetitions, positive and negative look-ahead and look-behind +assertions, "standalone" subexpressions, and conditional +subpatterns. The following Perl features are (currently) not +supported: + +

    + +
  • (?{ code }) and (??{ code }) because +they obviously don't make sense in Lisp. + +
  • \N{name} (named characters), \x{263a} +(wide hex characters), \l, \u, +\L, and \U +because they're actually not part of Perl's regex syntax and +(honestly) because I was too lazy - but see CL-INTERPOL. + +
  • \pP and \PP (named properties), +\X (extended Unicode), and \C (single +character). But you can of course use all characters +supported by your CL implementation. + +
  • Posix character classes like [[:alpha]]. I +might add this in the future. + +
  • \G for Perl's pos() because we don't have it. + +
+ +Note, however, that \t, \n, \r, +\f, \a, \e, \033 +(octal character codes), \x1B (hexadecimal character +codes), \c[ (control characters), \w, +\W, \s, \S, \d, +\D, \b, \B, \A, +\Z, and \z are supported. +

+Since version 0.6.0 CL-PPCRE also supports Perl's \Q and \E - see *ALLOW-QUOTING* below. Make sure you also read the relevant section in "Bugs and problems." +

+The keyword arguments are just for your +convenience. You can always use embedded modifiers like +"(?i-s)" instead.

+ +


[Method] +
create-scanner (function function)&key case-insensitive-mode multi-line-mode single-line-mode extended-mode destructive => scanner +


+In this case function should be a scanner returned by another invocation of CREATE-SCANNER. It will be returned as is. +
+ +


[Method] +
create-scanner (parse-tree t)&key case-insensitive-mode multi-line-mode single-line-mode extended-mode destructive => scanner +


+This is similar to CREATE-SCANNER for regex strings above but +accepts a parse tree as its first argument. A parse tree is an S-expression +conforming to the following syntax: + +
    + +
  • Every string and character is a parse tree and is treated +literally as a part of the regular expression, +i.e. parentheses, brackets, asterisks and such aren't special. + +
  • The symbol :VOID is equivalent to the empty string. + +
  • The symbol :EVERYTHING is equivalent to Perl's dot, +i.e it matches everything (except maybe a newline character depending +on the mode). + +
  • The symbols :WORD-BOUNDARY and +:NON-WORD-BOUNDARY are equivalent to Perl's +"\b" and "\B". + +
  • The symbols :DIGIT-CLASS, +:NON-DIGIT-CLASS, :WORD-CHAR-CLASS, +:NON-WORD-CHAR-CLASS, +:WHITESPACE-CHAR-CLASS, and +:NON-WHITESPACE-CHAR-CLASS are equivalent to Perl's +special character classes "\d", +"\D", "\w", +"\W", "\s", and +"\S" respectively. + +
  • The symbols :START-ANCHOR, :END-ANCHOR, +:MODELESS-START-ANCHOR, +:MODELESS-END-ANCHOR, and +:MODELESS-END-ANCHOR-NO-NEWLINE are equivalent to Perl's +"^", "$", +"\A", "\Z", and +"\z" respectively. + +
  • The symbols :CASE-INSENSITIVE-P, +:CASE-SENSITIVE-P, :MULTI-LINE-MODE-P, +:NOT-MULTI-LINE-MODE-P, :SINGLE-LINE-MODE-P, +and :NOT-SINGLE-LINE-MODE-P are equivalent to Perl's +embedded modifiers "(?i)", +"(?-i)", "(?m)", +"(?-m)", "(?s)", and +"(?-s)". As usual, changes applied to modes are +kept local to the innermost enclosing grouping or clustering +construct. + +
  • All other symbols will signal an error of type PPCRE-SYNTAX-ERROR +unless they are defined to be parse tree synonyms. + +
  • (:FLAGS {<modifier>}*) where +<modifier> is one of the modifier symbols from +above is used to group modifier symbols. The modifiers are applied +from left to right. (This construct is obviously redundant. It is only +there because it's used by the parser.) + +
  • (:SEQUENCE {<parse-tree>}*) means a +sequence of parse trees, i.e. the parse trees must match one after +another. Example: (:SEQUENCE #\f #\o #\o) is equivalent +to the parse tree "foo". + +
  • (:GROUP {<parse-tree>}*) is like +:SEQUENCE but changes applied to modifier flags (see +above) are kept local to the parse trees enclosed by this +construct. Think of it as the S-expression variant of Perl's +"(?:<pattern>)" construct. + +
  • (:ALTERNATION {<parse-tree>}*) means an +alternation of parse trees, i.e. one of the parse trees must +match. Example: (:ALTERNATION #\b #\a #\z) is equivalent +to the Perl regex string "b|a|z". + +
  • (:BRANCH <test> +<parse-tree>) is for conditional regular +expressions. <test> is either a number which +stands for a register or a parse tree which is a look-ahead or +look-behind assertion. See the entry for +(?(<condition>)<yes-pattern>|<no-pattern>) +in man +perlre for the semantics of this construct. If +<parse-tree> is an alternation is +must enclose exactly one or two parse trees where the second +one (if present) will be treated as the "no-pattern" - in +all other cases <parse-tree> will be treated +as the "yes-pattern". + +
  • (:POSITIVE-LOOKAHEAD|:NEGATIVE-LOOKAHEAD|:POSITIVE-LOOKBEHIND|:NEGATIVE-LOOKBEHIND +<parse-tree>) should be pretty obvious... + +
  • (:GREEDY-REPETITION|:NON-GREEDY-REPETITION +<min> <max> +<parse-tree>) where +<min> is a non-negative integer and +<max> is either a non-negative integer not +smaller than <min> or NIL will +result in a regular expression which tries to match +<parse-tree> at least +<min> times and at most +<max> times (or as often as possible if +<max> is NIL). So, e.g., +(:NON-GREEDY-REPETITION 0 1 "ab") is equivalent +to the Perl regex string "(?:ab)??". + +
  • (:STANDALONE <parse-tree>) is an +"independent" subexpression, i.e. (:STANDALONE +"bar") is equivalent to the Perl regex string +"(?>bar)". + +
  • (:REGISTER <parse-tree>) is a capturing +register group. As usual, registers are counted from left to right +beginning with 1. + +
  • (:BACK-REFERENCE <number>) where +<number> is a positive integer is a back-reference to a +register group. + +
  • (:FILTER <function> &optional +<length>) where +<function> is a function +designator and <length> is a +non-negative integer or NIL is a user-defined filter. + +
  • (:CHAR-CLASS|:INVERTED-CHAR-CLASS +{<item>}*) where <item> +is either a character, a character range, or a symbol for a +special character class (see above) will be translated into a (one +character wide) character class. A character range looks like +(:RANGE <char1> <char2>) where +<char1> and +<char2> are characters such that +(CHAR<= <char1> <char2>) is +true. Example: (:INVERTED-CHAR-CLASS #\a (:RANGE #\D #\G) +:DIGIT-CLASS) is equivalent to the Perl regex string +"[^aD-G\d]". + +
+ +Because CREATE-SCANNER is defined as a generic function +which dispatches on its first argument there's a certain ambiguity: +Although strings are valid parse trees they will be interpreted as +Perl regex strings when given to CREATE-SCANNER. To +circumvent this you can always use the equivalent parse tree (:GROUP +<string>) instead. +

+Note that CREATE-SCANNER doesn't always check +for the well-formedness of its first argument, i.e. you are expected +to provide correct parse trees. + +

+The usage of the keyword argument extended-mode obviously +doesn't make sense if CREATE-SCANNER is applied to parse +trees and will signal an error. +

+If destructive is not NIL (the default is +NIL) the function is allowed to destructively modify +parse-tree while creating the scanner. +

+If you want to find out how parse trees are related to Perl regex +strings you should play around with +CL-PPCRE::PARSE-STRING - a function which converts Perl +regex strings to parse trees. Here are some examples: + +

+* (cl-ppcre::parse-string "(ab)*")
+(:GREEDY-REPETITION 0 NIL (:REGISTER "ab"))
+
+* (cl-ppcre::parse-string "(a(b))")
+(:REGISTER (:SEQUENCE #\a (:REGISTER #\b)))
+
+* (cl-ppcre::parse-string "(?:abc){3,5}")
+(:GREEDY-REPETITION 3 5 (:GROUP "abc"))
+;; (:GREEDY-REPETITION 3 5 "abc") would also be OK
+
+* (cl-ppcre::parse-string "a(?i)b(?-i)c")
+(:SEQUENCE #\a
+ (:SEQUENCE (:FLAGS :CASE-INSENSITIVE-P)
+  (:SEQUENCE #\b (:SEQUENCE (:FLAGS :CASE-SENSITIVE-P) #\c))))
+;; same as (:SEQUENCE #\a :CASE-INSENSITIVE-P #\b :CASE-SENSITIVE-P #\c)
+
+* (cl-ppcre::parse-string "(?=a)b")
+(:SEQUENCE (:POSITIVE-LOOKAHEAD #\a) #\b)
+
+ +


[Accessor] +
parse-tree-synonym symbol => parse-tree +
(setf (parse-tree-synonym symbol) new-parse-tree)
+ +


+Any symbol (unless it's a keyword with a special meaning in parse +trees) can be made a "synonym", i.e. an abbreviation, for another parse +tree by this accessor. PARSE-TREE-SYNONYM returns NIL if symbol isn't a synonym yet. +

+Here's an example: + +

* (cl-ppcre::parse-string "a*b+")
+(:SEQUENCE (:GREEDY-REPETITION 0 NIL #\a) (:GREEDY-REPETITION 1 NIL #\b))
+
+* (defun my-repetition (char min)
+    `(:greedy-repetition ,min nil ,char))
+MY-REPETITION
+
+* (setf (parse-tree-synonym 'a*) (my-repetition #\a 0))
+(:GREEDY-REPETITION 0 NIL #\a)
+
+* (setf (parse-tree-synonym 'b+) (my-repetition #\b 1))
+(:GREEDY-REPETITION 1 NIL #\b)
+
+* (let ((scanner (create-scanner '(:sequence a* b+))))
+    (dolist (string '("ab" "b" "aab" "a" "x"))
+      (print (scan scanner string)))
+    (values))
+0
+0
+0
+NIL
+NIL
+
+* (parse-tree-synonym 'a*)
+(:GREEDY-REPETITION 0 NIL #\a)
+
+* (parse-tree-synonym 'a+)
+NIL
+
+ +


[Macro] +
define-parse-tree-synonym name parse-tree => parse-tree + +


+This is a convenience macro for parse tree synonyms defined as + +
(defmacro define-parse-tree-synonym (name parse-tree)
+  `(eval-when (:compile-toplevel :load-toplevel :execute)
+     (setf (parse-tree-synonym ',name) ',parse-tree)))
+
+ +so you can write code like this: + +
+(define-parse-tree-synonym a-z
+  (:char-class (:range #\a #\z) (:range #\a #\z)))
+
+(define-parse-tree-synonym a-z*
+  (:greedy-repetition 0 nil a-z))
+
+(defun ascii-char-tester (string)
+  (scan '(:sequence :start-anchor a-z* :end-anchor)
+        string))
+
+ +


+For the rest of this section regex can +always be a string (which is interpreted as a Perl regular +expression), a parse tree, or a scanner created by +CREATE-SCANNER. The +start and end +keyword parameters are always used as in SCAN. + + + + +


[Standard Generic Function] +
scan regex target-string &key start end => match-start, match-end, reg-starts, reg-ends + +


+Searches the string target-string from +start (which defaults to 0) to +end (which default to the length of +target-string) and tries to match +regex. On success returns four values - the start +of the match, the end of the match, and two arrays denoting the +beginnings and ends of register matches. On failure returns +NIL. target-string will be coerced to a +simple string if it isn't one already. +

+SCAN acts as if the part of +target-string between start +and end were a standalone string, i.e. look-aheads +and look-behinds can't look beyond these boundaries. +

+Examples: +

+* (cl-ppcre:scan "(a)*b" "xaaabd")
+1
+5
+#(3)
+#(4)
+
+* (cl-ppcre:scan "(a)*b" "xaaabd" :start 1)
+1
+5
+#(3)
+#(4)
+
+* (cl-ppcre:scan "(a)*b" "xaaabd" :start 2)
+2
+5
+#(3)
+#(4)
+
+* (cl-ppcre:scan "(a)*b" "xaaabd" :end 4)
+NIL
+
+* (cl-ppcre:scan '(:GREEDY-REPETITION 0 NIL #\b) "bbbc")
+0
+3
+#()
+#()
+
+* (cl-ppcre:scan '(:GREEDY-REPETITION 4 6 #\b) "bbbc")
+NIL
+
+* (let ((s (cl-ppcre:create-scanner "(([a-c])+)x")))
+    (cl-ppcre:scan s "abcxy"))
+0
+4
+#(0 2)
+#(3 3)
+
+ + + +


[Function] +
scan-to-strings regex target-string &key start end sharedp => match, regs + +


+Like SCAN but returns substrings of +target-string instead of positions, i.e. this +function returns two values on success: the whole match as a string +plus an array of substrings (or NILs) corresponding to +the matched registers. If sharedp is true, the substrings may share structure with +target-string. +

+Examples: +

+* (cl-ppcre:scan-to-strings "[^b]*b" "aaabd")
+"aaab"
+#()
+
+* (cl-ppcre:scan-to-strings "([^b])*b" "aaabd")
+"aaab"
+#("a")
+
+* (cl-ppcre:scan-to-strings "(([^b])*)b" "aaabd")
+"aaab"
+#("aaa" "a")
+
+ + +


[Macro] +
register-groups-bind var-list (regex target-string &key start end sharedp) declaration* statement* => result* + +


+Evaluates statement* with the variables in var-list bound to the +corresponding register groups after target-string has been matched +against regex, i.e. each variable is either +bound to a string or to NIL. +As a shortcut, the elements of var-list can also be lists of the form (FN VAR) where VAR is the variable symbol +and FN is a function +designator (which is evaluated) denoting a function which is to be applied to the string before the result is bound to VAR. +To make this even more convenient the form (FN VAR1 ...VARn) can be used as an abbreviation for +(FN VAR1) ... (FN VARn). +

+If there is no match, the statement* forms are not +executed. For each element of +var-list which is NIL there's no binding to the corresponding register +group. The number of variables in var-list must not be greater than +the number of register groups. If sharedp is true, the substrings may +share structure with target-string. +

Examples: +

+* (register-groups-bind (first second third fourth)
+      ("((a)|(b)|(c))+" "abababc" :sharedp t)
+    (list first second third fourth))
+("c" "a" "b" "c")
+
+* (register-groups-bind (nil second third fourth)
+      ;; note that we don't bind the first and fifth register group
+      ("((a)|(b)|(c))()+" "abababc" :start 6)
+    (list second third fourth))
+(NIL NIL "c")
+
+* (register-groups-bind (first)
+      ("(a|b)+" "accc" :start 1)
+    (format t "This will not be printed: ~A" first))
+NIL
+
+* (register-groups-bind (fname lname (#'parse-integer date month year))
+      ("(\\w+)\\s+(\\w+)\\s+(\\d{1,2})\\.(\\d{1,2})\\.(\\d{4})" "Frank Zappa 21.12.1940")
+    (list fname lname (encode-universal-time 0 0 0 date month year)))
+("Frank" "Zappa" 1292882400)
+
+
+ +


[Macro] +
do-scans (match-start match-end reg-starts reg-ends regex target-string &optional result-form &key start end) declaration* statement* => result* + +


+A macro which iterates over target-string and +tries to match regex as often as possible +evaluating statement* with +match-start, match-end, +reg-starts, and reg-ends bound +to the four return values of each match (see SCAN) in turn. After the last match, +returns result-form if provided or +NIL otherwise. An implicit block named NIL +surrounds DO-SCANS; RETURN may be used to +terminate the loop immediately. If regex matches +an empty string the scan is continued one position behind this match. +

+This is the most general macro to iterate over all matches in a target +string. See the source code of DO-MATCHES, ALL-MATCHES, SPLIT, or REGEX-REPLACE-ALL for examples of its +usage.

+ + + + +


[Macro] +
do-matches (match-start match-end regex target-string &optional result-form &key start end) declaration* statement* => result* + +


+Like DO-SCANS but doesn't bind +variables to the register arrays. +

Example: +

+* (defun foo (regex target-string &key (start 0) (end (length target-string)))
+    (let ((sum 0))
+      (cl-ppcre:do-matches (s e regex target-string nil :start start :end end)
+        (incf sum (- e s)))
+      (format t "~,2F% of the string was inside of a match~%"
+                ;; note: doesn't check for division by zero
+                (float (* 100 (/ sum (- end start)))))))
+
+FOO
+
+* (foo "a" "abcabcabc")
+33.33% of the string was inside of a match
+NIL
+* (foo "aa|b" "aacabcbbc")
+55.56% of the string was inside of a match
+NIL
+
+ + + + +


[Macro] +
do-matches-as-strings (match-var regex target-string &optional result-form &key start end sharedp) declaration* statement* => result* + +


+Like DO-MATCHES but binds +match-var to the substring of +target-string corresponding to each match in turn. If sharedp is true, the substrings may share structure with +target-string. +

+Example: +

+* (defun crossfoot (target-string &key (start 0) (end (length target-string)))
+    (let ((sum 0))
+      (cl-ppcre:do-matches-as-strings (m :digit-class
+                                         target-string nil
+                                         :start start :end end)
+        (incf sum (parse-integer m)))
+      (if (< sum 10)
+        sum
+        (crossfoot (format nil "~A" sum)))))
+
+CROSSFOOT
+
+* (crossfoot "bar")
+0
+
+* (crossfoot "a3x")
+3
+
+* (crossfoot "12345")
+6
+
+ +Of course, in real life you would do this with DO-MATCHES and use the start and end keyword parameters of PARSE-INTEGER.
+ +


[Macro] +
do-register-groups var-list (regex target-string &optional result-form &key start end sharedp) declaration* statement* => result* + +


+Iterates over target-string and tries to match regex as often as +possible evaluating statement* with the variables in var-list bound to the +corresponding register groups for each match in turn, i.e. each +variable is either bound to a string or to NIL. You can use the same shortcuts and abbreviations as in REGISTER-GROUPS-BIND. The number of +variables in var-list must not be greater than the number of register +groups. For each element of +var-list which is NIL there's no binding to the corresponding register +group. After the last match, returns result-form if provided or NIL +otherwise. An implicit block named NIL surrounds DO-REGISTER-GROUPS; +RETURN may be used to terminate the loop immediately. If regex matches +an empty string the scan is continued one position behind this +match. If sharedp is true, the substrings may share structure with +target-string. +

Example: +

+* (do-register-groups (first second third fourth)
+      ("((a)|(b)|(c))" "abababc" nil :start 2 :sharedp t)
+    (print (list first second third fourth)))
+("a" "a" NIL NIL) 
+("b" NIL "b" NIL) 
+("a" "a" NIL NIL) 
+("b" NIL "b" NIL) 
+("c" NIL NIL "c")
+NIL
+
+* (let (result)
+    (do-register-groups ((#'parse-integer n) (#'intern sign) whitespace)
+        ("(\\d+)|(\\+|-|\\*|/)|(\\s+)" "12*15 - 42/3")
+      (unless whitespace
+        (push (or n sign) result)))
+    (nreverse result))
+(12 * 15 - 42 / 3)
+
+
+ + +


[Function] +
all-matches regex target-string &key start end => list + +


+Returns a list containing the start and end positions of all matches +of regex against +target-string, i.e. if there are N +matches the list contains (* 2 N) elements. If +regex matches an empty string the scan is +continued one position behind this match. +

+Examples: +

+* (cl-ppcre:all-matches "a" "foo bar baz")
+(5 6 9 10)
+
+* (cl-ppcre:all-matches "\\w*" "foo bar baz")
+(0 3 3 3 4 7 7 7 8 11 11 11)
+
+ + + + +


[Function] +
all-matches-as-strings regex target-string &key start end sharedp => list + +


+Like ALL-MATCHES but +returns a list of substrings instead. If sharedp is true, the substrings may share structure with +target-string. +

+Examples: +

+* (cl-ppcre:all-matches-as-strings "a" "foo bar baz")
+("a" "a")
+
+* (cl-ppcre:all-matches-as-strings "\\w*" "foo bar baz")
+("foo" "" "bar" "" "baz" "")
+
+ + + + + + +


[Function] +
split regex target-string &key start end limit with-registers-p omit-unmatched-p sharedp => list + +


+Matches regex against +target-string as often as possible and returns a +list of the substrings between the matches. If +with-registers-p is true, substrings corresponding +to matched registers are inserted into the list as well. If +omit-unmatched-p is true, unmatched registers will +simply be left out, otherwise they will show up as +NIL. limit limits the number of +elements returned - registers aren't counted. If +limit is NIL (or 0 which is +equivalent), trailing empty strings are removed from the result list. +If regex matches an empty string the scan is +continued one position behind this match. If sharedp is true, the substrings may share structure with +target-string. +

+Beginning with CL-PPCRE 0.2.0, this function also tries hard to be +Perl-compatible - thus the somewhat peculiar behaviour. But note that +it hasn't been as extensively tested as SCAN. +

+Examples: +

+* (cl-ppcre:split "\\s+" "foo   bar baz
+frob")
+("foo" "bar" "baz" "frob")
+
+* (cl-ppcre:split "\\s*" "foo bar   baz")
+("f" "o" "o" "b" "a" "r" "b" "a" "z")
+
+* (cl-ppcre:split "(\\s+)" "foo bar   baz")
+("foo" "bar" "baz")
+
+* (cl-ppcre:split "(\\s+)" "foo bar   baz" :with-registers-p t)
+("foo" " " "bar" "   " "baz")
+
+* (cl-ppcre:split "(\\s)(\\s*)" "foo bar   baz" :with-registers-p t)
+("foo" " " "" "bar" " " "  " "baz")
+
+* (cl-ppcre:split "(,)|(;)" "foo,bar;baz" :with-registers-p t)
+("foo" "," NIL "bar" NIL ";" "baz")
+
+* (cl-ppcre:split "(,)|(;)" "foo,bar;baz" :with-registers-p t :omit-unmatched-p t)
+("foo" "," "bar" ";" "baz")
+
+* (cl-ppcre:split ":" "a:b:c:d:e:f:g::")
+("a" "b" "c" "d" "e" "f" "g")
+
+* (cl-ppcre:split ":" "a:b:c:d:e:f:g::" :limit 1)
+("a:b:c:d:e:f:g::")
+
+* (cl-ppcre:split ":" "a:b:c:d:e:f:g::" :limit 2)
+("a" "b:c:d:e:f:g::")
+
+* (cl-ppcre:split ":" "a:b:c:d:e:f:g::" :limit 3)
+("a" "b" "c:d:e:f:g::")
+
+* (cl-ppcre:split ":" "a:b:c:d:e:f:g::" :limit 1000)
+("a" "b" "c" "d" "e" "f" "g" "" "")
+
+ + + + + +


[Function] +
regex-replace regex target-string replacement &key start end preserve-case simple-calls => list + +


Try to match target-string +between start and end against +regex and replace the first match with +replacement. +

+replacement can be a string which may contain the +special substrings "\&" for the whole +match, "\`" for the part of +target-string before the match, +"\'" for the part of +target-string after the match, +"\N" or "\{N}" for the +Nth register where N is a positive integer. +

+replacement can also be a function +designator in which case the match will be replaced with the +result of calling the function designated by +replacement with the arguments +target-string, start, +end, match-start, +match-end, reg-starts, and +reg-ends. (reg-starts and +reg-ends are arrays holding the start and end +positions of matched registers (or NIL) - the meaning of +the other arguments should be obvious.) +

+If simple-calls is true, a function designated by +replacement will instead be called with the +arguments match, register-1, +..., register-n where match is +the whole match as a string and register-1 to +register-n are the matched registers, also as +strings (or NIL). Note that these strings share structure with +target-string so you must not modify them. +

+Finally, replacement can be a list where each +element is a string (which will be inserted verbatim), one of the +symbols :match, :before-match, or +:after-match (corresponding to +"\&", "\`", and +"\'" above), an integer N +(representing register (1+ N)), or a function +designator. +

+If preserve-case is true (default is +NIL), the replacement will try to preserve the case (all +upper case, all lower case, or capitalized) of the match. The result +will always be a fresh +string, even if regex doesn't match. +

+Examples: + +

+* (cl-ppcre:regex-replace "fo+" "foo bar" "frob")
+"frob bar"
+
+* (cl-ppcre:regex-replace "fo+" "FOO bar" "frob")
+"FOO bar"
+
+* (cl-ppcre:regex-replace "(?i)fo+" "FOO bar" "frob")
+"frob bar"
+
+* (cl-ppcre:regex-replace "(?i)fo+" "FOO bar" "frob" :preserve-case t)
+"FROB bar"
+
+* (cl-ppcre:regex-replace "(?i)fo+" "Foo bar" "frob" :preserve-case t)
+"Frob bar"
+
+* (cl-ppcre:regex-replace "bar" "foo bar baz" "[frob (was '\\&' between '\\`' and '\\'')]")
+"foo [frob (was 'bar' between 'foo ' and ' baz')] baz"
+
+* (cl-ppcre:regex-replace "bar" "foo bar baz"
+                          '("[frob (was '" :match "' between '" :before-match "' and '" :after-match "')]"))
+"foo [frob (was 'bar' between 'foo ' and ' baz')] baz"
+
+ + +


[Function] +
regex-replace-all regex target-string replacement &key start end preserve-case simple-calls => list + +


+Like REGEX-REPLACE but replaces all matches. +

+Examples: + +

+* (cl-ppcre:regex-replace-all "(?i)fo+" "foo Fooo FOOOO bar" "frob" :preserve-case t)
+"frob Frob FROB bar"
+
+* (cl-ppcre:regex-replace-all "(?i)f(o+)" "foo Fooo FOOOO bar" "fr\\1b" :preserve-case t)
+"froob Frooob FROOOOB bar"
+
+* (let ((qp-regex (cl-ppcre:create-scanner "[\\x80-\\xff]")))
+    (defun encode-quoted-printable (string)
+      "Convert 8-bit string to quoted-printable representation."
+      ;; won't work for Corman Lisp because non-ASCII characters aren't 8-bit there
+      (flet ((convert (target-string start end match-start match-end reg-starts reg-ends)
+             (declare (ignore start end match-end reg-starts reg-ends))
+             (format nil "=~2,'0x" (char-code (char target-string match-start)))))
+        (cl-ppcre:regex-replace-all qp-regex string #'convert))))
+Converted ENCODE-QUOTED-PRINTABLE.
+ENCODE-QUOTED-PRINTABLE
+
+* (encode-quoted-printable "Fête Sørensen naïve Hühner Straße")
+"F=EAte S=F8rensen na=EFve H=FChner Stra=DFe"
+
+* (let ((url-regex (cl-ppcre:create-scanner "[^a-zA-Z0-9_\\-.]")))
+    (defun url-encode (string)
+      "URL-encode a string."
+      ;; won't work for Corman Lisp because non-ASCII characters aren't 8-bit there
+      (flet ((convert (target-string start end match-start match-end reg-starts reg-ends)
+             (declare (ignore start end match-end reg-starts reg-ends))
+             (format nil "%~2,'0x" (char-code (char target-string match-start)))))
+        (cl-ppcre:regex-replace-all url-regex string #'convert))))
+Converted URL-ENCODE.
+URL-ENCODE
+
+* (url-encode "Fête Sørensen naïve Hühner Straße")
+"F%EAte%20S%F8rensen%20na%EFve%20H%FChner%20Stra%DFe"
+
+* (defun how-many (target-string start end match-start match-end reg-starts reg-ends)
+    (declare (ignore start end match-start match-end))
+    (format nil "~A" (- (svref reg-ends 0)
+                        (svref reg-starts 0))))
+HOW-MANY
+
+* (cl-ppcre:regex-replace-all "{(.+?)}"
+                              "foo{...}bar{.....}{..}baz{....}frob"
+                              (list "[" 'how-many " dots]"))
+"foo[3 dots]bar[5 dots][2 dots]baz[4 dots]frob"
+
+* (let ((qp-regex (cl-ppcre:create-scanner "[\\x80-\\xff]")))
+    (defun encode-quoted-printable (string)
+      "Convert 8-bit string to quoted-printable representation.
+Version using SIMPLE-CALLS keyword argument."
+      ;; ;; won't work for Corman Lisp because non-ASCII characters aren't 8-bit there
+      (flet ((convert (match)
+               (format nil "=~2,'0x" (char-code (char match 0)))))
+        (cl-ppcre:regex-replace-all qp-regex string #'convert
+                                    :simple-calls t))))
+
+Converted ENCODE-QUOTED-PRINTABLE.
+ENCODE-QUOTED-PRINTABLE
+
+* (encode-quoted-printable "Fête Sørensen naïve Hühner Straße")
+"F=EAte S=F8rensen na=EFve H=FChner Stra=DFe"
+
+* (defun how-many (match first-register)
+    (declare (ignore match))
+    (format nil "~A" (length first-register)))
+HOW-MANY
+
+* (cl-ppcre:regex-replace-all "{(.+?)}"
+                              "foo{...}bar{.....}{..}baz{....}frob"
+                              (list "[" 'how-many " dots]")
+                              :simple-calls t)
+
+"foo[3 dots]bar[5 dots][2 dots]baz[4 dots]frob"
+
+ +


[Function] +
regex-apropos regex &optional packages &key case-insensitive => list + +


+Like APROPOS +but searches for interned symbols which match the regular expression +regex. The output is implementation-dependent. If +case-insensitive is true (which is the default) +and regex isn't already a scanner, a +case-insensitive scanner is used. +

+Here are examples for CMUCL: + +

+* *package*
+#<The COMMON-LISP-USER package, 16/21 internal, 0/9 external>
+
+* (defun foo (n &optional (k 0)) (+ 3 n k))
+FOO
+
+* (defparameter foo "bar")
+FOO
+
+* (defparameter |foobar| 42)
+|foobar|
+
+* (defparameter fooboo 43)
+FOOBOO
+
+* (defclass frobar () ())
+#<STANDARD-CLASS FROBAR {4874E625}>
+
+* (cl-ppcre:regex-apropos "foo(?:bar)?")
+FOO [variable] value: "bar"
+    [compiled function] (N &OPTIONAL (K 0))
+FOOBOO [variable] value: 43
+|foobar| [variable] value: 42
+
+* (cl-ppcre:regex-apropos "(?:foo|fro)bar")
+PCL::|COMMON-LISP-USER::FROBAR class predicate| [compiled closure]
+FROBAR [class] #<STANDARD-CLASS FROBAR {4874E625}>
+|foobar| [variable] value: 42
+
+* (cl-ppcre:regex-apropos "(?:foo|fro)bar" 'cl-user)
+FROBAR [class] #<STANDARD-CLASS FROBAR {4874E625}>
+|foobar| [variable] value: 42
+
+* (cl-ppcre:regex-apropos "(?:foo|fro)bar" '(pcl ext))
+PCL::|COMMON-LISP-USER::FROBAR class predicate| [compiled closure]
+
+* (cl-ppcre:regex-apropos "foo")
+FOO [variable] value: "bar"
+    [compiled function] (N &OPTIONAL (K 0))
+FOOBOO [variable] value: 43
+|foobar| [variable] value: 42
+
+* (cl-ppcre:regex-apropos "foo" nil :case-insensitive nil)
+|foobar| [variable] value: 42
+
+ + + + +


[Function] +
regex-apropos-list regex &optional packages &key upcase => list + +


+Like APROPOS-LIST +but searches for interned symbols which match the regular expression +regex. If case-insensitive is +true (which is the default) and regex isn't +already a scanner, a case-insensitive scanner is used. +

+Example (continued from above): + +

+* (cl-ppcre:regex-apropos-list "foo(?:bar)?")
+(|foobar| FOOBOO FOO)
+
+ +


[Special variable] +
*regex-char-code-limit* + +


This variable controls whether scanners take into +account all characters of your CL implementation or only those the CHAR-CODE +of which is not larger than its value. It is only relevant if the +regular expression contains certain character classes. The default is +CHAR-CODE-LIMIT, +and you might see significant speed and space improvements during +scanner creation if, say, your target strings only contain ISO-8859-1 +characters and you're using an implementation like AllegroCL, +LispWorks, or CLISP where CHAR-CODE-LIMIT has a value +much higher than 255. The test suite will +automatically set *REGEX-CHAR-CODE-LIMIT* to 255 while +you're running the default test. +

+Here's an example with LispWorks: + +

+CL-USER 23 > (time (cl-ppcre:create-scanner "[3\\D]"))
+Timing the evaluation of (CL-PPCRE:CREATE-SCANNER "[3\\D]")
+
+user time    =      0.443
+system time  =      0.001
+Elapsed time =   0:00:01
+Allocation   = 546600 bytes standard / 2162611 bytes fixlen
+0 Page faults
+#<closure 20654AF2>
+
+CL-USER 24 > (time (let ((cl-ppcre:*regex-char-code-limit* 255)) (cl-ppcre:create-scanner "[3\\D]")))
+Timing the evaluation of (LET ((CL-PPCRE:*REGEX-CHAR-CODE-LIMIT* 255)) (CL-PPCRE:CREATE-SCANNER "[3\\D]"))
+
+user time    =      0.000
+system time  =      0.000
+Elapsed time =   0:00:00
+Allocation   = 3336 bytes standard / 8338 bytes fixlen
+0 Page faults
+#<closure 206569DA>
+
+

+Note: Due to the nature of LOAD-TIME-VALUE and the compiler macro for SCAN some +scanners might be created in a null +lexical environment at load time or at compile time so be careful +to which value *REGEX-CHAR-CODE-LIMIT* is bound at that +time. The default value should always yield correct results unless you +play dirty tricks with implementation-dependent behaviour, though.

+ +


[Special variable] +
*use-bmh-matchers* + +


Usually, the scanners created by CREATE-SCANNER (or +implicitely by other functions and macros) will use fast Boyer-Moore-Horspool +matchers to check for constant strings at the start or end of the +regular expression. If *USE-BMH-MATCHERS* is +NIL (the default is T), the standard +function SEARCH +will be used instead. This will usually be a bit slower but can save +lots of space if you're storing many scanners. The test suite will automatically set +*USE-BMH-MATCHERS* to NIL while you're running +the default test. +

+Note: Due to the nature of LOAD-TIME-VALUE and the compiler macro for SCAN some +scanners might be created in a null +lexical environment at load time or at compile time so be careful +to which value *USE-BMH-MATCHERS* is bound at that +time.

+ +


[Special variable] +
*allow-quoting* + +


+If this value is true (the default is NIL) +CL-PPCRE will support \Q and \E in regex +strings to quote (disable) metacharacters. Note that this entails a +slight performance penalty when creating scanners because (a copy of) the regex +string is modified (probably more than once) before it +is fed to the parser. Also, the parser's syntax error messages will complain +about the converted string and not about the original regex string. + +
+* (cl-ppcre:scan "^a+$" "a+")
+NIL
+
+* (let ((cl-ppcre:*allow-quoting* t))
+    (cl-ppcre:scan "^\\Qa+\\E$" "a+"))
+0
+2
+#()
+#()
+
+* (let ((cl-ppcre:*allow-quoting* t))
+    (cl-ppcre:scan "\\Qa()\\E(?#comment\\Q)a**b" "()ab"))
+
+Quantifier '*' not allowed at position 19 in string "a\\(\\)(?#commentQ)a**b"
+
+ +Note how in the last example the regex string in the error message is +different from the first argument to the SCAN +function. Also note that the second example might be easier to +understand (and Lisp-ier) if you write it like this: + +
+* (cl-ppcre:scan '(:sequence :start-anchor
+                             "a+" ;; no quoting necessary
+                             :end-anchor)
+                 "a+")
+0
+2
+#()
+#()
+
+ +Make sure you also read the relevant section in "Bugs and problems." + +
+ +


[Function] +
quote-meta-chars string => string' + +


+This is a simple utility function used when *ALLOW-QUOTING* is +true. It returns a string STRING' where all +non-word characters (everything except ASCII characters, digits and +underline) of STRING are quoted by prepending a +backslash similar to Perl's quotemeta function. It always returns a fresh +string. +
+* (cl-ppcre:quote-meta-chars "[a-z]*")
+"\\[a\\-z\\]\\*"
+
+ +


[Condition type] +
ppcre-error + +


+Every error signaled by CL-PPCRE is of type +PPCRE-ERROR. This is a direct subtype of SIMPLE-ERROR +without any additional slots or options. +
+ +


[Condition type] +
ppcre-invocation-error + +


+Errors of type PPCRE-INVOCATION-ERROR +are signaled if one of the exported functions of CL-PPCRE is called with wrong or +inconsistent arguments. This is a direct subtype of PPCRE-ERROR without any +additional slots or options. +
+ +


[Condition type] +
ppcre-syntax-error + +


+An error of type PPCRE-SYNTAX-ERROR is signaled if +CL-PPCRE's parser encounters an error when trying to parse a regex +string or to convert a parse tree into its internal representation. +This is a direct subtype of PPCRE-ERROR with two additional +slots. These denote the regex string which HTML-PPCRE was parsing and +the position within the string where the error occured. If the error +happens while CL-PPCRE is converting a parse tree both of these slots +contain NIL. (See the next two entries on how to access +these slots.) +

+As many syntax errors can't be detected before the parser is at the +end of the stream, the row and column usually denote the last position +where the parser was happy and not the position where it gave up. + +

+* (handler-case
+    (cl-ppcre:scan "foo**x" "fooox")
+    (cl-ppcre:ppcre-syntax-error (condition)
+      (format t "Houston, we've got a problem with the string ~S:~%~
+                 Looks like something went wrong at position ~A.~%~
+                 The last message we received was \"~?\"."
+              (cl-ppcre:ppcre-syntax-error-string condition)
+              (cl-ppcre:ppcre-syntax-error-pos condition)
+              (simple-condition-format-control condition)
+              (simple-condition-format-arguments condition))
+      (values)))
+Houston, we've got a problem with the string "foo**x":
+Looks like something went wrong at position 4.
+The last message we received was "Quantifier '*' not allowed".
+
+
+ +


[Function] +
ppcre-syntax-error-string condition => string + +


+If condition is a condition of type PPCRE-SYNTAX-ERROR this +function will return the string the parser was parsing when the error was +encountered (or NIL if the error happened while trying to +convert a parse tree). This might be particularly useful when *ALLOW-QUOTING* is +true because in this case the offending string might not be the one you gave to the CREATE-SCANNER function. +
+ +


[Function] +
ppcre-syntax-error-pos condition => number + +


+If condition is a condition of type PPCRE-SYNTAX-ERROR this +function will return the position within the string where the error +occured (or NIL if the error happened while trying to +convert a parse tree). +
+ + +
 

Filters

+ +Because several users have asked for it, CL-PPCRE now offers +"filters" (see above for syntax) +which are basically arbitrary, user-defined functions that can act as +regex building blocks. Filters can only be used within parse trees, not within Perl regex +strings. +

+Note that filters are currently considered an experimental feature and +their API might change in the future. +

+A filter is defined by its filter function which must be a +function of one argument. During the parsing process this function +might be called once or several times or it might not be called at +all. If it's called its argument is an integer pos +which is the current position within the target string. The filter can +either return NIL (which means that the subexpression +represented by this filter didn't match) or an integer not smaller +than pos for success. A zero-length assertion +should return pos itself while a filter which +wants to consume N characters should return +(+ POS N). +

+If you supply the optional value length and it is +not NIL then this is a promise to the regex engine that +your filter will always consume exactly +length characters. The regex engine might use this +information for optimization purposes but it is otherwise irrelevant +to the outcome of the matching process. +

+The filter function can access the following special variables from +its code body: +

    + +
  • CL-PPCRE::*STRING*: The target (a string) of the +current matching process. + +
  • CL-PPCRE::*START-POS* and +CL-PPCRE::*END-POS*: The start and end (integers) indices +of the current matching process. These correspond to the +START and END keyword parameters of SCAN. + +
  • CL-PPCRE::*REAL-START-POS*: The initial starting +position. This is only relevant for repeated scans (as in DO-SCANS) where +CL-PPCRE::*START-POS* will be moved forward while +CL-PPCRE::*REAL-START-POS* won't. For normal scans the +value of this variable is NIL. + +
  • CL-PPCRE::*REG-STARTS* and +CL-PPCRE::*REG-ENDS*: Two simple vectors which denote the +start and end indices of registers within the regular expression. The +first register is indexed by 0. If a register hasn't matched yet +then its corresponding entry in CL-PPCRE::*REG-STARTS* is +NIL. + +
+ +These variables should be considered read-only. Do not change +these values unless you really know what you're doing! +

+Note that the names of the variables are not exported from the +CL-PPCRE package because there's currently no guarantee +that they will be available in future releases. +

+Here are some filter examples: +

+* (defun my-info-filter (pos)
+    "Show some info about the matching process."
+    (format t "Called at position ~A~%" pos)
+    (loop with dim = (array-dimension cl-ppcre::*reg-starts* 0)
+          for i below dim
+          for reg-start = (aref cl-ppcre::*reg-starts* i)
+          for reg-end = (aref cl-ppcre::*reg-ends* i)
+          do (format t "Register ~A is currently " (1+ i))
+          when reg-start
+               (write-string cl-ppcre::*string* nil
+            do (write-char #\')
+               (write-string cl-ppcre::*string* nil
+                     :start reg-start :end reg-end)
+               (write-char #\')
+          else
+            do (write-string "unbound")
+          do (terpri))
+    (terpri)
+    pos)
+MY-INFO-FILTER
+
+* (scan '(:sequence
+           (:register
+             (:greedy-repetition 0 nil
+                                 (:char-class (:range #\a #\z))))
+           (:filter my-info-filter 0) "X")
+        "bYcdeX")
+Called at position 1
+Register 1 is currently 'b'
+
+Called at position 0
+Register 1 is currently ''
+
+Called at position 1
+Register 1 is currently ''
+
+Called at position 5
+Register 1 is currently 'cde'
+
+2
+6
+#(2)
+#(5)
+
+* (scan '(:sequence
+           (:register
+             (:greedy-repetition 0 nil
+                                 (:char-class (:range #\a #\z))))
+           (:filter my-info-filter 0) "X")
+        "bYcdeZ")
+NIL
+
+* (defun my-weird-filter (pos)
+    "Only match at this point if either pos is odd and the character
+  we're looking at is lowerrcase or if pos is even and the next two
+  characters we're looking at are uppercase. Consume these characters if
+  there's a match."
+    (format t "Trying at position ~A~%" pos)
+    (cond ((and (oddp pos)
+                (< pos cl-ppcre::*end-pos*)
+                (lower-case-p (char cl-ppcre::*string* pos)))
+           (1+ pos))
+          ((and (evenp pos)
+                (< (1+ pos) cl-ppcre::*end-pos*)
+                (upper-case-p (char cl-ppcre::*string* pos))
+                (upper-case-p (char cl-ppcre::*string* (1+ pos))))
+           (+ pos 2))
+          (t nil)))
+MY-WEIRD-FILTER
+
+* (defparameter *weird-regex*
+                `(:sequence "+" (:filter ,#'my-weird-filter) "+"))
+*WEIRD-REGEX*
+
+* (scan *weird-regex* "+A++a+AA+")
+Trying at position 1
+Trying at position 3
+Trying at position 4
+Trying at position 6
+5
+9
+#()
+#()
+
+* (fmakunbound 'my-weird-filter)
+MY-WEIRD-FILTER
+
+* (scan *weird-regex* "+A++a+AA+")
+Trying at position 1
+Trying at position 3
+Trying at position 4
+Trying at position 6
+5
+9
+#()
+#()
+
+ +Note that in the second call to SCAN our filter wasn't +invoked at all - it was optimized away by the regex engine because it +knew that it couldn't match. Also note that *WEIRD-REGEX* +still worked after we removed the global function definition of +MY-WEIRD-FILTER because the regular expression had +captured the original definition. + +

+ +For more ideas about what you can do with filters see this +thread on the mailing list. + +
 

Testing CL-PPCRE

+ +CL-PPCRE comes with a comprehensive test suite most of which is stolen +from the PCRE library. You can use +it like this: + +
+* (mk:compile-system "cl-ppcre-test")
+; Loading #p"/home/edi/cl-ppcre/cl-ppcre.system".
+; Loading #p"/home/edi/cl-ppcre/packages.x86f".
+; Loading #p"/home/edi/cl-ppcre/specials.x86f".
+; Loading #p"/home/edi/cl-ppcre/util.x86f".
+; Loading #p"/home/edi/cl-ppcre/errors.x86f".
+; Loading #p"/home/edi/cl-ppcre/lexer.x86f".
+; Loading #p"/home/edi/cl-ppcre/parser.x86f".
+; Loading #p"/home/edi/cl-ppcre/regex-class.x86f".
+; Loading #p"/home/edi/cl-ppcre/convert.x86f".
+; Loading #p"/home/edi/cl-ppcre/optimize.x86f".
+; Loading #p"/home/edi/cl-ppcre/closures.x86f".
+; Loading #p"/home/edi/cl-ppcre/repetition-closures.x86f".
+; Loading #p"/home/edi/cl-ppcre/scanner.x86f".
+; Loading #p"/home/edi/cl-ppcre/api.x86f".
+; Loading #p"/home/edi/cl-ppcre/ppcre-tests.x86f".
+NIL
+
+* (cl-ppcre-test:test)
+
+;; ....
+;; (a list of incompatibilities with Perl)
+
+ +(If you're not using MK:DEFSYSTEM or asdf it suffices to build +CL-PPCRE and then compile and load the file +ppcre-tests.lisp.) +

+With LispWorks, SCL, and SBCL (starting from version 0.8.4.8) you can also call +CL-PPCRE-TEST:TEST with a keyword argument argument +THREADED which - in addition to the usual tests - will +also check whether the scanners created by CL-PPCRE are thread-safe. +

+Note that the file testdata provided with CL-PPCRE +was created on a Linux system with Perl 5.8.0. You can (and you +should if you're on Mac OS or Windows) create your own +testdata with the Perl script +perltest.pl: + +

+edi@bird:~/cl-ppcre > perl perltest.pl < testinput > testdata
+
+ +Of course you can also create your own tests - the format accepted by +perltest.pl should be rather clear from looking at the +file testinput. Note that the target strings are wrapped +in double quotes and then fed to Perl's eval so you can +use ugly Perl constructs like, say, a@{['b' x 10]}c which +will result in the target string +"abbbbbbbbbbc". + +
 

Compatibility with Perl

+ +Depending on your Perl version you might encounter a couple of small +incompatibilities with Perl most of which aren't due to CL-PPCRE: + +

Empty strings instead of undef in $1, $2, etc.

+ +(Cf. case #629 of testdata.) +This is a +bug in Perl 5.6.1 and earlier which has been fixed in 5.8.0. + +

Strange scoping of embedded modifiers

+ +(Cf. case #430 of testdata.) +This is a +bug in Perl 5.6.1 and earlier which has been fixed in 5.8.0. + +

Inconsistent capturing of $1, $2, etc.

+ +(Cf. case #662 of testdata.) +This is a +bug in Perl which hasn't been fixed yet. + +

Captured groups not available outside of look-aheads and look-behinds

+ +(Cf. case #1439 of testdata.) +Well, OK, this ain't a Perl bug. I just can't quite understand why +captured groups should only be seen within the scope of a look-ahead +or look-behind. For the moment, CL-PPCRE and Perl agree to +disagree... :) + +

Alternations don't always work from left to right

+ +(Cf. case #790 of testdata.) I +also think this a Perl bug but I currently have lost the drive to +report it. + +

"\r" doesn't work with MCL

+ +(Cf. case #9 of testdata.) For +some strange reason that I don't understand MCL translates +#\Return to (CODE-CHAR 10) while MacPerl +translates "\r" to (CODE-CHAR +13). Hmmm... + +

What about "\w"?

+ +CL-PPCRE uses ALPHANUMERICP +to decide whether a character matches Perl's +"\w", so depending on your CL implementation +you might encounter differences between Perl and CL-PPCRE when +matching non-ASCII characters. + +
 

Performance

+ +

Benchmarking

+ +The CL-PPCRE test suite can also be used for +benchmarking purposes: If you call perltest.pl with a +command line argument it will be interpreted as the minimum number of seconds +each test should run. Perl will time its tests accordingly and create +output which, when fed to CL-PPCRE-TEST:TEST, will result +in a benchmark. Here's an example: + +
+edi@bird:~/cl-ppcre > echo "/((a{0,5}){0,5})*[c]/
+aaaaaaaaaaaac
+
+/((a{0,5})*)*[c]/
+aaaaaaaaaaaac" | perl perltest.pl .5 > timedata
+1
+2
+
+edi@bird:~/cl-ppcre > cmucl -quiet
+; Loading #p"/home/edi/.cmucl-init".
+
+* (mk:compile-system "cl-ppcre-test")
+; Loading #p"/home/edi/cl-ppcre/cl-ppcre.system".
+; Loading #p"/home/edi/cl-ppcre/packages.x86f".
+; Loading #p"/home/edi/cl-ppcre/specials.x86f".
+; Loading #p"/home/edi/cl-ppcre/util.x86f".
+; Loading #p"/home/edi/cl-ppcre/errors.x86f".
+; Loading #p"/home/edi/cl-ppcre/lexer.x86f".
+; Loading #p"/home/edi/cl-ppcre/parser.x86f".
+; Loading #p"/home/edi/cl-ppcre/regex-class.x86f".
+; Loading #p"/home/edi/cl-ppcre/convert.x86f".
+; Loading #p"/home/edi/cl-ppcre/optimize.x86f".
+; Loading #p"/home/edi/cl-ppcre/closures.x86f".
+; Loading #p"/home/edi/cl-ppcre/repetition-closures.x86f".
+; Loading #p"/home/edi/cl-ppcre/scanner.x86f".
+; Loading #p"/home/edi/cl-ppcre/api.x86f".
+; Loading #p"/home/edi/cl-ppcre/ppcre-tests.x86f".
+NIL
+
+* (cl-ppcre-test:test :file-name "/home/edi/cl-ppcre/timedata")
+   1: 0.5559 (1000000 repetitions, Perl: 4.5330 seconds, CL-PPCRE: 2.5200 seconds)
+   2: 0.4573 (1000000 repetitions, Perl: 4.5922 seconds, CL-PPCRE: 2.1000 seconds)
+NIL
+
+ +We gave two test cases to perltest.pl and asked it to repeat those tests often enough so that it takes at least 0.5 seconds to run each of them. In both cases, CMUCL was about twice as fast as Perl. +

+Here are some more benchmarks (done with Perl 5.6.1 and CMUCL 18d+): +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test caseRepetitionsPerl (sec)CL-PPCRE (sec)Ratio CL-PPCRE/Perl
"@{['x' x 100]}" =~ /(.)*/s1000000.13940.07000.5022
"@{['x' x 1000]}" =~ /(.)*/s1000000.16280.06000.3685
"@{['x' x 10000]}" =~ /(.)*/s1000000.50710.06000.1183
"@{['x' x 100000]}" =~ /(.)*/s100000.39020.00000.0000
"@{['x' x 100]}" =~ /.*/1000000.15200.08000.5262
"@{['x' x 1000]}" =~ /.*/1000000.37860.54001.4263
"@{['x' x 10000]}" =~ /.*/100000.27090.51001.8826
"@{['x' x 100000]}" =~ /.*/10000.27340.51001.8656
"@{['x' x 100]}" =~ /.*/s1000000.13200.03000.2274
"@{['x' x 1000]}" =~ /.*/s1000000.16340.03000.1836
"@{['x' x 10000]}" =~ /.*/s1000000.53040.03000.0566
"@{['x' x 100000]}" =~ /.*/s100000.39660.00000.0000
"@{['x' x 100]}" =~ /x*/1000000.15070.09000.5970
"@{['x' x 1000]}" =~ /x*/1000000.37820.63001.6658
"@{['x' x 10000]}" =~ /x*/100000.27300.60002.1981
"@{['x' x 100000]}" =~ /x*/10000.27080.59002.1790
"@{['x' x 100]}" =~ /[xy]*/1000000.26370.15000.5688
"@{['x' x 1000]}" =~ /[xy]*/100000.14490.12000.8282
"@{['x' x 10000]}" =~ /[xy]*/10000.13440.11000.8185
"@{['x' x 100000]}" =~ /[xy]*/1000.13550.12000.8857
"@{['x' x 100]}" =~ /(.)*/1000000.15230.11000.7220
"@{['x' x 1000]}" =~ /(.)*/1000000.37350.57001.5262
"@{['x' x 10000]}" =~ /(.)*/100000.27350.51001.8647
"@{['x' x 100000]}" =~ /(.)*/10000.25980.50001.9242
"@{['x' x 100]}" =~ /(x)*/1000000.15650.13000.8307
"@{['x' x 1000]}" =~ /(x)*/1000000.37830.66001.7446
"@{['x' x 10000]}" =~ /(x)*/100000.27200.60002.2055
"@{['x' x 100000]}" =~ /(x)*/10000.27250.60002.2020
"@{['x' x 100]}" =~ /(y|x)*/100000.24110.10000.4147
"@{['x' x 1000]}" =~ /(y|x)*/10000.23130.09000.3891
"@{['x' x 10000]}" =~ /(y|x)*/1000.23360.09000.3852
"@{['x' x 100000]}" =~ /(y|x)*/100.41650.09000.2161
"@{['x' x 100]}" =~ /([xy])*/1000000.26780.18000.6721
"@{['x' x 1000]}" =~ /([xy])*/100000.14590.12000.8227
"@{['x' x 10000]}" =~ /([xy])*/10000.13720.11000.8017
"@{['x' x 100000]}" =~ /([xy])*/1000.13580.11000.8098
"@{['x' x 100]}" =~ /((x){2})*/100000.10730.04000.3727
"@{['x' x 1000]}" =~ /((x){2})*/100000.91460.24000.2624
"@{['x' x 10000]}" =~ /((x){2})*/10000.90200.23000.2550
"@{['x' x 100000]}" =~ /((x){2})*/1000.89830.23000.2560
"@{[join undef, map { chr(ord('a') + rand 26) } (1..100)]}FOOBARBAZ" =~ /[a-z]*FOOBARBAZ/1000000.28290.23000.8129
"@{[join undef, map { chr(ord('a') + rand 26) } (1..1000)]}FOOBARBAZ" =~ /[a-z]*FOOBARBAZ/100000.18590.17000.9143
"@{[join undef, map { chr(ord('a') + rand 26) } (1..10000)]}FOOBARBAZ" =~ /[a-z]*FOOBARBAZ/10000.14200.17001.1968
"@{[join undef, map { chr(ord('a') + rand 26) } (1..100)]}NOPE" =~ /[a-z]*FOOBARBAZ/10000000.91960.46000.5002
"@{[join undef, map { chr(ord('a') + rand 26) } (1..1000)]}NOPE" =~ /[a-z]*FOOBARBAZ/1000000.21660.25001.1542
"@{[join undef, map { chr(ord('a') + rand 26) } (1..10000)]}NOPE" =~ /[a-z]*FOOBARBAZ/100000.14650.23001.5696
"@{[join undef, map { chr(ord('a') + rand 26) } (1..100)]}FOOBARBAZ" =~ /([a-z])*FOOBARBAZ/1000000.29170.26000.8915
"@{[join undef, map { chr(ord('a') + rand 26) } (1..1000)]}FOOBARBAZ" =~ /([a-z])*FOOBARBAZ/100000.18110.18000.9942
"@{[join undef, map { chr(ord('a') + rand 26) } (1..10000)]}FOOBARBAZ" =~ /([a-z])*FOOBARBAZ/10000.14240.16001.1233
"@{[join undef, map { chr(ord('a') + rand 26) } (1..100)]}NOPE" =~ /([a-z])*FOOBARBAZ/10000000.91540.74000.8083
"@{[join undef, map { chr(ord('a') + rand 26) } (1..1000)]}NOPE" =~ /([a-z])*FOOBARBAZ/1000000.21700.28001.2901
"@{[join undef, map { chr(ord('a') + rand 26) } (1..10000)]}NOPE" =~ /([a-z])*FOOBARBAZ/100000.14970.23001.5360
"@{[join undef, map { chr(ord('a') + rand 26) } (1..100)]}FOOBARBAZ" =~ /([a-z]|ab)*FOOBARBAZ/100000.43590.15000.3441
"@{[join undef, map { chr(ord('a') + rand 26) } (1..1000)]}FOOBARBAZ" =~ /([a-z]|ab)*FOOBARBAZ/10000.54560.15000.2749
"@{[join undef, map { chr(ord('a') + rand 26) } (1..10000)]}FOOBARBAZ" =~ /([a-z]|ab)*FOOBARBAZ/100.20390.06000.2943
"@{[join undef, map { chr(ord('a') + rand 26) } (1..100)]}NOPE" =~ /([a-z]|ab)*FOOBARBAZ/10000000.93110.74000.7947
"@{[join undef, map { chr(ord('a') + rand 26) } (1..1000)]}NOPE" =~ /([a-z]|ab)*FOOBARBAZ/1000000.21620.27001.2489
"@{[join undef, map { chr(ord('a') + rand 26) } (1..10000)]}NOPE" =~ /([a-z]|ab)*FOOBARBAZ/100000.14880.23001.5455
"@{[join undef, map { chr(ord('a') + rand 26) } (1..100)]}NOPE" =~ /[a-z]*FOOBARBAZ/i10000.15550.00000.0000
"@{[join undef, map { chr(ord('a') + rand 26) } (1..1000)]}NOPE" =~ /[a-z]*FOOBARBAZ/i100.14410.00000.0000
"@{[join undef, map { chr(ord('a') + rand 26) } (1..10000)]}NOPE" =~ /[a-z]*FOOBARBAZ/i1013.71500.01000.0007
+ +

+As you might have noticed, Perl shines if it can reduce significant +parts of the matching process to cases where it can advance through +the target string one character at a time. This leads to C code where +you can very efficiently test and increment a pointer into a string in +a tight loop and can hardly be beaten with CL. In almost all other +cases, the CMUCL/CL-PPCRE combination is usually faster than Perl - +sometimes a lot faster. +

+As most of the examples above were chosen to make Perl look good +here's another benchmark - the +result of running perltest.pl against the +full testdata file with a time +limit of 0.1 seconds, CL-PPCRE 0.1.2 on CMUCL 18e-pre +vs. Perl 5.6.1. CL-PPCRE is faster than Perl in 1511 of 1545 +cases - in 1045 cases it's more than twice as fast. +

+Note that Perl as well as CL-PPCRE keep the rightmost matches in +registers - keep that in mind if you benchmark against other regex +implementations. Also note that CL-PPCRE-TEST:TEST +automatically skips test cases where Perl and CL-PPCRE don't agree. + +

Other performance issues

+ +While the scanners created by CL-PPCRE are pretty fast, the process +which creates scanners from Perl regex strings and parse trees isn't +that speedy and conses a lot. It is recommended that you store and +re-use scanners if possible. The DO-macros will do this +for you automatically. +

+However, beginning with version 0.5.2, CL-PPCRE uses a compiler +macro and LOAD-TIME-VALUE +to make sure that the scanner is only built once if the first argument +to SCAN, SCAN-TO-STRINGS, SPLIT, +REGEX-REPLACE, or REGEX-REPLACE-ALL is a constant +form. (But see the notes for *REGEX-CHAR-CODE-LIMIT* and +*USE-BMH-MATCHERS*.) +

+Here's an example of its effect + +

+* (trace cl-ppcre::convert)
+(CL-PPCRE::CONVERT)
+* (defun foo (string) (cl-ppcre:scan "(?s).*" string))
+FOO
+* (time (foo "The quick brown fox"))
+Compiling LAMBDA NIL: 
+Compiling Top-Level Form: 
+
+  0: (CL-PPCRE::CONVERT #<lambda-list-unavailable>)
+  0: CL-PPCRE::CONVERT returned
+       #<CL-PPCRE::SEQ {48B033C5}>
+       0
+       #<CL-PPCRE::EVERYTHING {48B031D5}>
+Evaluation took:
+  0.0 seconds of real time
+  0.00293 seconds of user run time
+  9.77e-4 seconds of system run time
+  0 page faults and
+  11,408 bytes consed.
+0
+19
+#()
+#()
+* (time (foo "The quick brown fox"))
+Compiling LAMBDA NIL: 
+Compiling Top-Level Form: 
+
+  0: (CL-PPCRE::CONVERT #<lambda-list-unavailable>)
+  0: CL-PPCRE::CONVERT returned
+       #<CL-PPCRE::SEQ {48B14C4D}>
+       0
+       #<CL-PPCRE::EVERYTHING {48B14B65}>
+Evaluation took:
+  0.0 seconds of real time
+  0.00293 seconds of user run time
+  0.0 seconds of system run time
+  0 page faults and
+  10,960 bytes consed.
+0
+19
+#()
+#()
+* (compile 'foo)
+  0: (CL-PPCRE::CONVERT #<lambda-list-unavailable>)
+  0: CL-PPCRE::CONVERT returned
+       #<CL-PPCRE::SEQ {48B1FEC5}>
+       0
+       #<CL-PPCRE::EVERYTHING {48B1FDDD}>
+Compiling LAMBDA (STRING): 
+Compiling Top-Level Form: 
+FOO
+NIL
+NIL
+* (time (foo "The quick brown fox"))
+Compiling LAMBDA NIL: 
+Compiling Top-Level Form: 
+
+Evaluation took:
+  0.0 seconds of real time
+  0.0 seconds of user run time
+  0.0 seconds of system run time
+  0 page faults and
+  0 bytes consed.
+0
+19
+#()
+#()
+* (time (foo "The quick brown fox"))
+Compiling LAMBDA NIL: 
+Compiling Top-Level Form: 
+
+Evaluation took:
+  0.0 seconds of real time
+  0.0 seconds of user run time
+  0.0 seconds of system run time
+  0 page faults and
+  0 bytes consed.
+0
+19
+#()
+#()
+* 
+
+ +

+Of course, the usual rules for creating efficient regular expressions +apply to CL-PPCRE as well although it can optimize a couple of cases +itself. The most important rule is probably that you shouldn't use +capturing groups if you don't need the captured information, i.e. use +"(?:a|b)*" instead of +"(a|b)*" if you don't need to refer to the +register. (In fact, in this particular case CL-PPCRE will be able to +optimize away the register group, but it won't if you replace +"a|b" with, say, +"a|bc".) +

+Another point worth mentioning is that you definitely should use +single-line mode if you have long strings without +#\Newline (or where you don't care about the line breaks) +and plan to use regular expressions like +".*". See the benchmarks +for comparisons between single-line mode and normal mode with such +target strings. +

+Another thing to consider is that, for performance reasons, CL-PPCRE +assumes that most of the target strings you're trying to match are simple +strings and coerces non-simple strings to simple strings before +scanning them. If you plan on working with non-simple strings mostly +you might consider modifying the CL-PPCRE source code. This is easy: +Change all occurences of SCHAR to CHAR and +redefine the macro in util.lisp where the coercion takes +place - that's all. + +
 

Bugs and problems

+ +

Stack overflow

+ +CL-PPCRE can optimize away a lot of unnecessary backtracking but +sometimes this simply isn't possible. With complicated regular +expressions and long strings this might lead to stack overflows +depending on your machine and your CL implementation. +

+Here's one example with CLISP: + +

+[1]> (defun target (n) (concatenate 'string (make-string n :initial-element #\a) "b"))
+TARGET
+
+[2]> (cl-ppcre:scan "a*" (target 1000))
+0 ;
+1000 ;
+#() ;
+#()
+
+[3]> (cl-ppcre:scan "(?:a|b)*" (target 1000))
+0 ;
+1001 ;
+#() ;
+#()
+
+[4]> (cl-ppcre:scan "(a|b)*" (target 1000))
+0 ;
+1001 ;
+#(1000) ;
+#(1001)
+
+[5]> (cl-ppcre:scan "(a|b)*" (target 10000))
+0 ;
+10001 ;
+#(10000) ;
+#(10001)
+
+[6]> (cl-ppcre:scan "(a|b)*" (target 100000))
+0 ;
+100001 ;
+#(100000) ;
+#(100001)
+
+[7]> (cl-ppcre:scan "(a|b)*" (target 1000000))
+0 ;
+1000001 ;
+#(1000000) ;
+#(1000001)
+
+;; No problem until now - but...
+
+[8]> (cl-ppcre:scan "(a|)*" (target 100000))
+*** - Lisp stack overflow. RESET
+
+[9]> (cl-ppcre:scan "(a|)*" (target 3200))
+*** - Lisp stack overflow. RESET
+
+ +

+With CMUCL the situation is better and worse at the same time. It will +take a lot longer until CMUCL gives up but if it gives up the whole +Lisp image will silently die (at least on my machine): +

+[Note: This was true for CMUCL 18e - CMUCL 19a behaves in a much nicer way and gives you a chance to recover.] + +

+* (defun target (n) (concatenate 'string (make-string n :initial-element #\a) "b"))
+TARGET
+
+* (cl-ppcre:scan "(a|)*" (target 3200))
+0
+3200
+#(3200)
+#(3200)
+
+* (cl-ppcre:scan "(a|)*" (target 10000))
+0
+10000
+#(10000)
+#(10000)
+
+* (cl-ppcre:scan "(a|)*" (target 100000))
+0
+100000
+#(100000)
+#(100000)
+
+* (cl-ppcre:scan "(a|)*" (target 1000000))
+0
+1000000
+#(1000000)
+#(1000000)
+
+;; No problem until now - but...
+
+* (cl-ppcre:scan "(a|)*" (target 10000000))
+edi@bird:~ >
+
+ +This behaviour can be changed with very conservative optimization settings but that'll make CL-PPCRE crawl compared to Perl. + +

+You might want to compare this to the way Perl handles the same situation. It might lie to you: + +

+edi@bird:~ > perl -le '$_="a" x 32766 . "b"; /(a|)*/; print $1'
+
+edi@bird:~ > perl -le '$_="a" x 32767 . "b"; /(a|)*/; print $1'
+a
+
+ +Or it might warn you before it's lying to you: +
+edi@bird:~ > perl -lwe '$_="a" x 32767 . "b"; /(a|)*/; print $1'
+Complex regular subexpression recursion limit (32766) exceeded at -e line 1.
+a
+
+ +Or it might simply die: +
+edi@bird:~ > /opt/perl-5.8/bin/perl -lwe '$_="a" x 32767 . "b"; /(a|)*/; print $1'
+Segmentation fault
+
+ +Your mileage may vary, of course... + +

"\Q" doesn't work, or does it?

+ +In Perl the following code works as expected, i.e. it prints 1. +
+#!/usr/bin/perl -l
+
+$a = '\E*';
+print 1
+  if '\E*\E*' =~ /(?:\Q$a\E){2}/;
+
+ +If you try to do something similar in CL-PPCRE you get an error: + +
+* (let ((cl-ppcre:*allow-quoting* t)
+        (a "\\E*"))
+    (cl-ppcre:scan (concatenate 'string "(?:\\Q" a "\\E){2}") "\\E*\\E*"))
+Quantifier '*' not allowed at position 3 in string "(?:*\\E){2}"
+
+ +The error message might give you a hint as to why this happens: +Because *ALLOW-QUOTING* +was true the concatenated string was pre-processed before it +was fed to CL-PPCRE's parser - the result of this pre-processing is +"(?:*\\E){2}" because the +"\\E" in the string A was taken to +be the end of the quoted section started by +"\\Q". This cannot happen in Perl due to its +complicated interpolation rules - see man perlop for +the scary details. It can happen in CL-PPCRE, though. +Bummer! +

+What gives? "\\Q...\\E" in CL-PPCRE should only +be used in literal strings. If you want to quote arbitrary strings +try CL-INTERPOL or use QUOTE-META-CHARS: +

+* (let ((a "\\E*"))
+    (cl-ppcre:scan (concatenate 'string
+                                "(?:" (cl-ppcre:quote-meta-chars a) "){2}")
+                   "\\E*\\E*"))
+0
+6
+#()
+#()
+
+Or, even better and Lisp-ier, use the S-expression syntax instead - no need for quoting in this case: +
+* (let ((a "\\E*"))
+    (cl-ppcre:scan `(:greedy-repetition 2 2 ,a)
+                   "\\E*\\E*"))
+0
+6
+#()
+#()
+
+ +

Backslashes may confuse you...

+ +
+* (let ((a "y\\y"))
+    (cl-ppcre:scan a a))
+NIL
+
+ +You didn't expect this to yield NIL, did you? Shouldn't something like (CL-PPCRE:SCAN A A) always return a true value? No, because the first and the second argument to SCAN are handled differently: The first argument is fed to CL-PPCRE's parser and is treated like a Perl regular expression. In particular, the parser "sees" \y and converts it to y because \y has no special meaning in regular expressions. So, the regular expression is the constant string "yy". But the second argument isn't converted - it is left as is, i.e. it's equivalent to Perl's 'y\y'. In other words, this example would be equivalent to the Perl code + +
+'y\y' =~ /y\y/;
+
+ +or to + +
+$a = 'y\y';
+$a =~ /$a/;
+
+ +which should explain why it doesn't match. +

+Still confused? You might want to try CL-INTERPOL. + +
 

Remarks

+ +The sample output from CMUCL and CLISP has been slightly edited to +increase readability. +

+All test cases and benchmarks in this document where performed on an +IBM Thinkpad T23 laptop (Pentium III 1.2 GHz, +768 MB RAM) running Gentoo +Linux 1.1a. + +
 

AllegroCL compatibility mode

+ +Since autumn 2004 AllegroCL offers +a +new regular expression API with a syntax very similar to +CL-PPCRE. Although CL-PPCRE is quite fast already, AllegroCL's engine will +most likely be even faster (but only on AllegroCL, of course). However, you might want to +stick to CL-PPCRE because you have a "legacy" application or because +you want your code to be portable to other Lisp implementations. +Therefore, beginning from version 1.2.0, CL-PPCRE offers a +"compatibility mode" where you can continue using the CL-PPCRE API as +described above but deploy the AllegroCL regex +engine under the hood. (The details are: Calls to CREATE-SCANNER and SCAN are dispatched to their AllegroCL +counterparts EXCL:COMPILE-RE +and EXCL:MATCH-RE +while everything else is left as is.) +

+The advantage of this mode is that you'll get a much smaller image and +most likely faster code. (But note that CL-PPCRE needs to do a small amount of work to massage AllegroCL's output into the format expected by CL-PPCRE.) The downside is that your code won't be +fully compatible with CL-PPCRE anymore. Here are some of the +differences (most of which probably don't matter very often): +

+For more details about the AllegroCL engine and possible deviations from CL-PPCRE see the documentation at the Franz Inc. website. +

+To use the AllegroCL compatibility mode you have to +

+(push :use-acl-regexp2-engine *features*)
+
+before you compile CL-PPCRE. + +
 

Acknowledgements

+ +Although I didn't use their code I was heavily inspired by looking at +the Scheme/CL regex implementations of Dorai +Sitaram and Michael +Parker. Also, the nice folks from CMUCL's mailing list as well +as the output of Perl's use re "debug" pragma +have been very helpful in optimizing the scanners created by CL-PPCRE. + +

+The asdf system definitions were kindly provided by Marco +Baringer. Hannu Koivisto provided patches to make the +.system files more usable. Thanks to Kevin Rosenberg and +Douglas Crosher for pointing out how to be friendly to case-sensitive +ACL images. Thanks to Karsten Poeck and JP Massar for their help in +making CL-PPCRE work with Corman Lisp. JP Massar and Kent M. Pitman +also helped to improve/fix the test suite and the compiler macro. + +

+Thanks to the guys at "Café Olé" in Hamburg +where I wrote most of the code and thanks to my wife for lending me +her PowerBook to test CL-PPCRE with MCL and OpenMCL. + +

+$Header: /usr/local/cvsrep/cl-ppcre/doc/index.html,v 1.113 2005/02/02 18:35:54 edi Exp $ +

BACK TO MY HOMEPAGE + + + \ No newline at end of file diff --git a/practicals/libraries/cl-ppcre-1.2.3/errors.lisp b/practicals/libraries/cl-ppcre-1.2.3/errors.lisp new file mode 100644 index 0000000..a279e6d --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/errors.lisp @@ -0,0 +1,84 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/errors.lisp,v 1.13 2004/09/30 09:58:42 edi Exp $ + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre) + +(defvar *syntax-error-string* nil + "The string which caused the syntax error.") + +(define-condition ppcre-error (simple-error) + () + (:documentation "All errors signaled by CL-PPCRE are of +this type.")) + +(define-condition ppcre-syntax-error (ppcre-error) + ((string :initarg :string + :reader ppcre-syntax-error-string) + (pos :initarg :pos + :reader ppcre-syntax-error-pos)) + (:default-initargs + :pos nil + :string *syntax-error-string*) + (:report (lambda (condition stream) + (format stream "~?~@[ at position ~A~]~@[ in string ~S~]" + (simple-condition-format-control condition) + (simple-condition-format-arguments condition) + (ppcre-syntax-error-pos condition) + (ppcre-syntax-error-string condition)))) + (:documentation "Signaled if CL-PPCRE's parser encounters an error +when trying to parse a regex string or to convert a parse tree into +its internal representation.")) + +(setf (documentation 'ppcre-syntax-error-string 'function) + "Returns the string the parser was parsing when the error was +encountered \(or NIL if the error happened while trying to convert a +parse tree).") + +(setf (documentation 'ppcre-syntax-error-pos 'function) + "Returns the position within the string where the error occured +\(or NIL if the error happened while trying to convert a parse tree") + +(define-condition ppcre-invocation-error (ppcre-error) + () + (:documentation "Signaled when CL-PPCRE functions are +invoked with wrong arguments.")) + +(defmacro signal-ppcre-syntax-error* (pos format-control &rest format-arguments) + `(error 'ppcre-syntax-error + :pos ,pos + :format-control ,format-control + :format-arguments (list ,@format-arguments))) + +(defmacro signal-ppcre-syntax-error (format-control &rest format-arguments) + `(signal-ppcre-syntax-error* nil ,format-control ,@format-arguments)) + +(defmacro signal-ppcre-invocation-error (format-control &rest format-arguments) + `(error 'ppcre-invocation-error + :format-control ,format-control + :format-arguments (list ,@format-arguments))) diff --git a/practicals/libraries/cl-ppcre-1.2.3/lexer.lisp b/practicals/libraries/cl-ppcre-1.2.3/lexer.lisp new file mode 100644 index 0000000..e464fb1 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/lexer.lisp @@ -0,0 +1,769 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/lexer.lisp,v 1.21 2004/09/30 09:58:42 edi Exp $ + +;;; The lexer's responsibility is to convert the regex string into a +;;; sequence of tokens which are in turn consumed by the parser. +;;; +;;; The lexer is aware of Perl's 'extended mode' and it also 'knows' +;;; (with a little help from the parser) how many register groups it +;;; has opened so far. (The latter is necessary for interpreting +;;; strings like "\\10" correctly.) + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre) + +(declaim (inline map-char-to-special-class)) +(defun map-char-to-special-char-class (chr) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Maps escaped characters like \"\\d\" to the tokens which represent +their associated character classes." + (case chr + ((#\d) + :digit-class) + ((#\D) + :non-digit-class) + ((#\w) + :word-char-class) + ((#\W) + :non-word-char-class) + ((#\s) + :whitespace-char-class) + ((#\S) + :non-whitespace-char-class))) + +(locally + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (defstruct (lexer (:constructor make-lexer-internal)) + "LEXER structures are used to hold the regex string which is +currently lexed and to keep track of the lexer's state." + (str "" + :type string + :read-only t) + (len 0 + :type fixnum + :read-only t) + (reg 0 + :type fixnum) + (pos 0 + :type fixnum) + (last-pos nil + :type list))) + +(defun make-lexer (string) + (declare (inline make-lexer-internal) + #-genera (type string string)) + (make-lexer-internal :str (maybe-coerce-to-simple-string string) + :len (length string))) + +(declaim (inline end-of-string-p)) +(defun end-of-string-p (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Tests whether we're at the end of the regex string." + (<= (lexer-len lexer) + (lexer-pos lexer))) + +(declaim (inline looking-at-p)) +(defun looking-at-p (lexer chr) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Tests whether the next character the lexer would see is CHR. +Does not respect extended mode." + (and (not (end-of-string-p lexer)) + (char= (schar (lexer-str lexer) (lexer-pos lexer)) + chr))) + +(declaim (inline next-char-non-extended)) +(defun next-char-non-extended (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Returns the next character which is to be examined and updates the +POS slot. Does not respect extended mode." + (cond ((end-of-string-p lexer) + nil) + (t + (prog1 + (schar (lexer-str lexer) (lexer-pos lexer)) + (incf (lexer-pos lexer)))))) + +(defun next-char (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Returns the next character which is to be examined and updates the +POS slot. Respects extended mode, i.e. whitespace, comments, and also +nested comments are skipped if applicable." + (let ((next-char (next-char-non-extended lexer)) + last-loop-pos) + (loop + ;; remember where we started + (setq last-loop-pos (lexer-pos lexer)) + ;; first we look for nested comments like (?#foo) + (when (and next-char + (char= next-char #\() + (looking-at-p lexer #\?)) + (incf (lexer-pos lexer)) + (cond ((looking-at-p lexer #\#) + ;; must be a nested comment - so we have to search for + ;; the closing parenthesis + (let ((error-pos (- (lexer-pos lexer) 2))) + (unless + ;; loop 'til ')' or end of regex string and + ;; return NIL if ')' wasn't encountered + (loop for skip-char = next-char + then (next-char-non-extended lexer) + while (and skip-char + (char/= skip-char #\))) + finally (return skip-char)) + (signal-ppcre-syntax-error* + error-pos + "Comment group not closed"))) + (setq next-char (next-char-non-extended lexer))) + (t + ;; undo effect of previous INCF if we didn't see a # + (decf (lexer-pos lexer))))) + (when *extended-mode-p* + ;; now - if we're in extended mode - we skip whitespace and + ;; comments; repeat the following loop while we look at + ;; whitespace or #\# + (loop while (and next-char + (or (char= next-char #\#) + (whitespacep next-char))) + do (setq next-char + (if (char= next-char #\#) + ;; if we saw a comment marker skip until + ;; we're behind #\Newline... + (loop for skip-char = next-char + then (next-char-non-extended lexer) + while (and skip-char + (char/= skip-char #\Newline)) + finally (return (next-char-non-extended lexer))) + ;; ...otherwise (whitespace) skip until we + ;; see the next non-whitespace character + (loop for skip-char = next-char + then (next-char-non-extended lexer) + while (and skip-char + (whitespacep skip-char)) + finally (return skip-char)))))) + ;; if the position has moved we have to repeat our tests + ;; because of cases like /^a (?#xxx) (?#yyy) {3}c/x which + ;; would be equivalent to /^a{3}c/ in Perl + (unless (> (lexer-pos lexer) last-loop-pos) + (return next-char))))) + +(declaim (inline fail)) +(defun fail (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Moves (LEXER-POS LEXER) back to the last position stored in +\(LEXER-LAST-POS LEXER) and pops the LAST-POS stack." + (unless (lexer-last-pos lexer) + (signal-ppcre-syntax-error "LAST-POS stack of LEXER ~A is empty" lexer)) + (setf (lexer-pos lexer) (pop (lexer-last-pos lexer))) + nil) + +(defun get-number (lexer &key (radix 10) max-length no-whitespace-p) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Read and consume the number the lexer is currently looking at and +return it. Returns NIL if no number could be identified. +RADIX is used as in PARSE-INTEGER. If MAX-LENGTH is not NIL we'll read +at most the next MAX-LENGTH characters. If NO-WHITESPACE-P is not NIL +we don't tolerate whitespace in front of the number." + (when (or (end-of-string-p lexer) + (and no-whitespace-p + (whitespacep (schar (lexer-str lexer) (lexer-pos lexer))))) + (return-from get-number nil)) + (multiple-value-bind (integer new-pos) + (parse-integer (lexer-str lexer) + :start (lexer-pos lexer) + :end (if max-length + (let ((end-pos (+ (lexer-pos lexer) + (the fixnum max-length))) + (lexer-len (lexer-len lexer))) + (if (< end-pos lexer-len) + end-pos + lexer-len)) + (lexer-len lexer)) + :radix radix + :junk-allowed t) + (cond ((and integer (>= (the fixnum integer) 0)) + (setf (lexer-pos lexer) new-pos) + integer) + (t nil)))) + +(declaim (inline try-number)) +(defun try-number (lexer &key (radix 10) max-length no-whitespace-p) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Like GET-NUMBER but won't consume anything if no number is seen." + ;; remember current position + (push (lexer-pos lexer) (lexer-last-pos lexer)) + (let ((number (get-number lexer + :radix radix + :max-length max-length + :no-whitespace-p no-whitespace-p))) + (or number (fail lexer)))) + +(declaim (inline make-char-from-code)) +(defun make-char-from-code (number error-pos) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Create character from char-code NUMBER. NUMBER can be NIL +which is interpreted as 0. ERROR-POS is the position where +the corresponding number started within the regex string." + ;; Only look at rightmost eight bits in compliance with Perl + (let ((code (logand #o377 (the fixnum (or number 0))))) + (or (and (< code char-code-limit) + (code-char code)) + (signal-ppcre-syntax-error* + error-pos + "No character for hex-code ~X" + number)))) + +(defun unescape-char (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Convert the characters(s) following a backslash into a token +which is returned. This function is to be called when the backslash +has already been consumed. Special character classes like \\W are +handled elsewhere." + (when (end-of-string-p lexer) + (signal-ppcre-syntax-error "String ends with backslash")) + (let ((chr (next-char-non-extended lexer))) + (case chr + ((#\E) + ;; if \Q quoting is on this is ignored, otherwise it's just an + ;; #\E + (if *allow-quoting* + :void + #\E)) + ((#\c) + ;; \cx means control-x in Perl + (let ((next-char (next-char-non-extended lexer))) + (unless next-char + (signal-ppcre-syntax-error* + (lexer-pos lexer) + "Character missing after '\\c' at position ~A")) + (code-char (logxor #x40 (char-code (char-upcase next-char)))))) + ((#\x) + ;; \x should be followed by a hexadecimal char code, + ;; two digits or less + (let* ((error-pos (lexer-pos lexer)) + (number (get-number lexer :radix 16 :max-length 2 :no-whitespace-p t))) + ;; note that it is OK if \x is followed by zero digits + (make-char-from-code number error-pos))) + ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) + ;; \x should be followed by an octal char code, + ;; three digits or less + (let* ((error-pos (decf (lexer-pos lexer))) + (number (get-number lexer :radix 8 :max-length 3))) + (make-char-from-code number error-pos))) + ;; the following five character names are 'semi-standard' + ;; according to the CLHS but I'm not aware of any implementation + ;; that doesn't implement them + ((#\t) + #\Tab) + ((#\n) + #\Newline) + ((#\r) + #\Return) + ((#\f) + #\Page) + ((#\b) + #\Backspace) + ((#\a) + (code-char 7)) ; ASCII bell + ((#\e) + (code-char 27)) ; ASCII escape + (otherwise + ;; all other characters aren't affected by a backslash + chr)))) + +(defun collect-char-class (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Reads and consumes characters from regex string until a right +bracket is seen. Assembles them into a list \(which is returned) of +characters, character ranges, like \(:RANGE #\\A #\\E) for a-e, and +tokens representing special character classes." + (let ((start-pos (lexer-pos lexer)) ; remember start for error message + hyphen-seen + last-char + list) + (flet ((handle-char (c) + "Do the right thing with character C depending on whether +we're inside a range or not." + (cond ((and hyphen-seen last-char) + (setf (car list) (list :range last-char c) + last-char nil)) + (t + (push c list) + (setq last-char c))) + (setq hyphen-seen nil))) + (loop for first = t then nil + for c = (next-char-non-extended lexer) + ;; leave loop if at end of string + while c + do (cond + ((char= c #\\) + ;; we've seen a backslash + (let ((next-char (next-char-non-extended lexer))) + (case next-char + ((#\d #\D #\w #\W #\s #\S) + ;; a special character class + (push (map-char-to-special-char-class next-char) list) + ;; if the last character was a hyphen + ;; just collect it literally + (when hyphen-seen + (push #\- list)) + ;; if the next character is a hyphen do the same + (when (looking-at-p lexer #\-) + (push #\- list) + (incf (lexer-pos lexer))) + (setq hyphen-seen nil)) + ((#\E) + ;; if \Q quoting is on we ignore \E, + ;; otherwise it's just a plain #\E + (unless *allow-quoting* + (handle-char #\E))) + (otherwise + ;; otherwise unescape the following character(s) + (decf (lexer-pos lexer)) + (handle-char (unescape-char lexer)))))) + (first + ;; the first character must not be a right bracket + ;; and isn't treated specially if it's a hyphen + (handle-char c)) + ((char= c #\]) + ;; end of character class + ;; make sure we collect a pending hyphen + (when hyphen-seen + (setq hyphen-seen nil) + (handle-char #\-)) + ;; reverse the list to preserve the order intended + ;; by the author of the regex string + (return-from collect-char-class (nreverse list))) + ((and (char= c #\-) + last-char + (not hyphen-seen)) + ;; if the last character was 'just a character' + ;; we expect to be in the middle of a range + (setq hyphen-seen t)) + ((char= c #\-) + ;; otherwise this is just an ordinary hyphen + (handle-char #\-)) + (t + ;; default case - just collect the character + (handle-char c)))) + ;; we can only exit the loop normally if we've reached the end + ;; of the regex string without seeing a right bracket + (signal-ppcre-syntax-error* + start-pos + "Missing right bracket to close character class")))) + +(defun maybe-parse-flags (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Reads a sequence of modifiers \(including #\\- to reverse their +meaning) and returns a corresponding list of \"flag\" tokens. The +\"x\" modifier is treated specially in that it dynamically modifies +the behaviour of the lexer itself via the special variable +*EXTENDED-MODE-P*." + (prog1 + (loop with set = t + for chr = (next-char-non-extended lexer) + unless chr + do (signal-ppcre-syntax-error "Unexpected end of string") + while (find chr "-imsx" :test #'char=) + ;; the first #\- will invert the meaning of all modifiers + ;; following it + if (char= chr #\-) + do (setq set nil) + else if (char= chr #\x) + do (setq *extended-mode-p* set) + else collect (if set + (case chr + ((#\i) + :case-insensitive-p) + ((#\m) + :multi-line-mode-p) + ((#\s) + :single-line-mode-p)) + (case chr + ((#\i) + :case-sensitive-p) + ((#\m) + :not-multi-line-mode-p) + ((#\s) + :not-single-line-mode-p)))) + (decf (lexer-pos lexer)))) + +(defun get-quantifier (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Returns a list of two values (min max) if what the lexer is looking +at can be interpreted as a quantifier. Otherwise returns NIL and +resets the lexer to its old position." + ;; remember starting position for FAIL and UNGET-TOKEN functions + (push (lexer-pos lexer) (lexer-last-pos lexer)) + (let ((next-char (next-char lexer))) + (case next-char + ((#\*) + ;; * (Kleene star): match 0 or more times + '(0 nil)) + ((#\+) + ;; +: match 1 or more times + '(1 nil)) + ((#\?) + ;; ?: match 0 or 1 times + '(0 1)) + ((#\{) + ;; one of + ;; {n}: match exactly n times + ;; {n,}: match at least n times + ;; {n,m}: match at least n but not more than m times + ;; note that anything not matching one of these patterns will + ;; be interpreted literally - even whitespace isn't allowed + (let ((num1 (get-number lexer :no-whitespace-p t))) + (if num1 + (let ((next-char (next-char-non-extended lexer))) + (case next-char + ((#\,) + (let* ((num2 (get-number lexer :no-whitespace-p t)) + (next-char (next-char-non-extended lexer))) + (case next-char + ((#\}) + ;; this is the case {n,} (NUM2 is NIL) or {n,m} + (list num1 num2)) + (otherwise + (fail lexer))))) + ((#\}) + ;; this is the case {n} + (list num1 num1)) + (otherwise + (fail lexer)))) + ;; no number following left curly brace, so we treat it + ;; like a normal character + (fail lexer)))) + ;; cannot be a quantifier + (otherwise + (fail lexer))))) + +(defun get-token (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Returns and consumes the next token from the regex string (or NIL)." + ;; remember starting position for UNGET-TOKEN function + (push (lexer-pos lexer) + (lexer-last-pos lexer)) + (let ((next-char (next-char lexer))) + (cond (next-char + (case next-char + ;; the easy cases first - the following six characters + ;; always have a special meaning and get translated + ;; into tokens immediately + ((#\)) + :close-paren) + ((#\|) + :vertical-bar) + ((#\?) + :question-mark) + ((#\.) + :everything) + ((#\^) + :start-anchor) + ((#\$) + :end-anchor) + ((#\+ #\*) + ;; quantifiers will always be consumend by + ;; GET-QUANTIFIER, they must not appear here + (signal-ppcre-syntax-error* + (1- (lexer-pos lexer)) + "Quantifier '~A' not allowed" + next-char)) + ((#\{) + ;; left brace isn't a special character in it's own + ;; right but we must check if what follows might + ;; look like a quantifier + (let ((this-pos (lexer-pos lexer)) + (this-last-pos (lexer-last-pos lexer))) + (unget-token lexer) + (when (get-quantifier lexer) + (signal-ppcre-syntax-error* + (car this-last-pos) + "Quantifier '~A' not allowed" + (subseq (lexer-str lexer) + (car this-last-pos) + (lexer-pos lexer)))) + (setf (lexer-pos lexer) this-pos + (lexer-last-pos lexer) this-last-pos) + next-char)) + ((#\[) + ;; left bracket always starts a character class + (cons (cond ((looking-at-p lexer #\^) + (incf (lexer-pos lexer)) + :inverted-char-class) + (t + :char-class)) + (collect-char-class lexer))) + ((#\\) + ;; backslash might mean different things so we have + ;; to peek one char ahead: + (let ((next-char (next-char-non-extended lexer))) + (case next-char + ((#\A) + :modeless-start-anchor) + ((#\Z) + :modeless-end-anchor) + ((#\z) + :modeless-end-anchor-no-newline) + ((#\b) + :word-boundary) + ((#\B) + :non-word-boundary) + ((#\d #\D #\w #\W #\s #\S) + ;; these will be treated like character classes + (map-char-to-special-char-class next-char)) + ((#\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) + ;; uh, a digit... + (let* ((old-pos (decf (lexer-pos lexer))) + ;; ...so let's get the whole number first + (backref-number (get-number lexer))) + (declare (type fixnum backref-number)) + (cond ((and (> backref-number (lexer-reg lexer)) + (<= 10 backref-number)) + ;; \10 and higher are treated as octal + ;; character codes if we haven't + ;; opened that much register groups + ;; yet + (setf (lexer-pos lexer) old-pos) + ;; re-read the number from the old + ;; position and convert it to its + ;; corresponding character + (make-char-from-code (get-number lexer :radix 8 :max-length 3) + old-pos)) + (t + ;; otherwise this must refer to a + ;; backreference + (list :back-reference backref-number))))) + ((#\0) + ;; this always means an octal character code + ;; (at most three digits) + (let ((old-pos (decf (lexer-pos lexer)))) + (make-char-from-code (get-number lexer :radix 8 :max-length 3) + old-pos))) + (otherwise + ;; in all other cases just unescape the + ;; character + (decf (lexer-pos lexer)) + (unescape-char lexer))))) + ((#\() + ;; an open parenthesis might mean different things + ;; depending on what follows... + (cond ((looking-at-p lexer #\?) + ;; this is the case '(?' (and probably more behind) + (incf (lexer-pos lexer)) + ;; we have to check for modifiers first + ;; because a colon might follow + (let* ((flags (maybe-parse-flags lexer)) + (next-char (next-char-non-extended lexer))) + ;; modifiers are only allowed if a colon + ;; or a closing parenthesis are following + (when (and flags + (not (find next-char ":)" :test #'char=))) + (signal-ppcre-syntax-error* + (car (lexer-last-pos lexer)) + "Sequence '~A' not recognized" + (subseq (lexer-str lexer) + (car (lexer-last-pos lexer)) + (lexer-pos lexer)))) + (case next-char + ((nil) + ;; syntax error + (signal-ppcre-syntax-error + "End of string following '(?'")) + ((#\)) + ;; an empty group except for the flags + ;; (if there are any) + (or (and flags + (cons :flags flags)) + :void)) + ((#\() + ;; branch + :open-paren-paren) + ((#\>) + ;; standalone + :open-paren-greater) + ((#\=) + ;; positive look-ahead + :open-paren-equal) + ((#\!) + ;; negative look-ahead + :open-paren-exclamation) + ((#\:) + ;; non-capturing group - return flags as + ;; second value + (values :open-paren-colon flags)) + ((#\<) + ;; might be a look-behind assertion, so + ;; check next character + (let ((next-char (next-char-non-extended lexer))) + (case next-char + ((#\=) + ;; positive look-behind + :open-paren-less-equal) + ((#\!) + ;; negative look-behind + :open-paren-less-exclamation) + ((#\)) + ;; Perl allows "(?<)" and treats + ;; it like a null string + :void) + ((nil) + ;; syntax error + (signal-ppcre-syntax-error + "End of string following '(?<'")) + (t + ;; also syntax error + (signal-ppcre-syntax-error* + (1- (lexer-pos lexer)) + "Character '~A' may not follow '(?<'" + next-char ))))) + (otherwise + (signal-ppcre-syntax-error* + (1- (lexer-pos lexer)) + "Character '~A' may not follow '(?'" + next-char))))) + (t + ;; if next-char was not #\? (this is within + ;; the first COND), we've just seen an opening + ;; parenthesis and leave it like that + :open-paren))) + (otherwise + ;; all other characters are their own tokens + next-char))) + ;; we didn't get a character (this if the "else" branch from + ;; the first IF), so we don't return a token but NIL + (t + (pop (lexer-last-pos lexer)) + nil)))) + +(declaim (inline unget-token)) +(defun unget-token (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Moves the lexer back to the last position stored in the LAST-POS stack." + (if (lexer-last-pos lexer) + (setf (lexer-pos lexer) + (pop (lexer-last-pos lexer))) + (error "No token to unget \(this should not happen)"))) + +(declaim (inline start-of-subexpr-p)) +(defun start-of-subexpr-p (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Tests whether the next token can start a valid sub-expression, i.e. +a stand-alone regex." + (let* ((pos (lexer-pos lexer)) + (next-char (next-char lexer))) + (not (or (null next-char) + (prog1 + (member (the character next-char) + '(#\) #\|) + :test #'char=) + (setf (lexer-pos lexer) pos)))))) diff --git a/practicals/libraries/cl-ppcre-1.2.3/load.lisp b/practicals/libraries/cl-ppcre-1.2.3/load.lisp new file mode 100644 index 0000000..28a68a8 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/load.lisp @@ -0,0 +1,67 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/load.lisp,v 1.12 2005/02/02 18:34:30 edi Exp $ + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :cl-user) + +(let ((cl-ppcre-base-directory + (make-pathname :name nil :type nil :version nil + :defaults (parse-namestring *load-truename*))) + must-compile) + (with-compilation-unit () + (dolist (file '("packages" + "specials" + "util" + "errors" + #-:use-acl-regexp2-engine "lexer" + #-:use-acl-regexp2-engine "parser" + #-:use-acl-regexp2-engine "regex-class" + #-:use-acl-regexp2-engine "convert" + #-:use-acl-regexp2-engine "optimize" + #-:use-acl-regexp2-engine "closures" + #-:use-acl-regexp2-engine "repetition-closures" + #-:use-acl-regexp2-engine "scanner" + "api" + "ppcre-tests")) + (let ((pathname (make-pathname :name file :type "lisp" :version nil + :defaults cl-ppcre-base-directory))) + ;; don't use COMPILE-FILE in Corman Lisp, it's broken - LOAD + ;; will yield compiled functions anyway + #-:cormanlisp + (let ((compiled-pathname (compile-file-pathname pathname))) + (unless (and (not must-compile) + (probe-file compiled-pathname) + (< (file-write-date pathname) + (file-write-date compiled-pathname))) + (setq must-compile t) + (compile-file pathname)) + (setq pathname compiled-pathname)) + (load pathname))))) + + + diff --git a/practicals/libraries/cl-ppcre-1.2.3/optimize.lisp b/practicals/libraries/cl-ppcre-1.2.3/optimize.lisp new file mode 100644 index 0000000..d704dd3 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/optimize.lisp @@ -0,0 +1,582 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/optimize.lisp,v 1.22 2005/01/24 14:06:38 edi Exp $ + +;;; This file contains optimizations which can be applied to converted +;;; parse trees. + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre) + +(defgeneric flatten (regex) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Merges adjacent sequences and alternations, i.e. it +transforms # # #>> to +# # #>. This is a destructive +operation on REGEX.")) + +(defmethod flatten ((seq seq)) + ;; this looks more complicated than it is because we modify SEQ in + ;; place to avoid unnecessary consing + (let ((elements-rest (elements seq))) + (loop + (unless elements-rest + (return)) + (let ((flattened-element (flatten (car elements-rest))) + (next-elements-rest (cdr elements-rest))) + (cond ((typep flattened-element 'seq) + ;; FLATTENED-ELEMENT is a SEQ object, so we "splice" + ;; it into out list of elements + (let ((flattened-element-elements + (elements flattened-element))) + (setf (car elements-rest) + (car flattened-element-elements) + (cdr elements-rest) + (nconc (cdr flattened-element-elements) + (cdr elements-rest))))) + (t + ;; otherwise we just replace the current element with + ;; its flattened counterpart + (setf (car elements-rest) flattened-element))) + (setq elements-rest next-elements-rest)))) + (let ((elements (elements seq))) + (cond ((cadr elements) + seq) + ((cdr elements) + (first elements)) + (t (make-instance 'void))))) + +(defmethod flatten ((alternation alternation)) + ;; same algorithm as above + (let ((choices-rest (choices alternation))) + (loop + (unless choices-rest + (return)) + (let ((flattened-choice (flatten (car choices-rest))) + (next-choices-rest (cdr choices-rest))) + (cond ((typep flattened-choice 'alternation) + (let ((flattened-choice-choices + (choices flattened-choice))) + (setf (car choices-rest) + (car flattened-choice-choices) + (cdr choices-rest) + (nconc (cdr flattened-choice-choices) + (cdr choices-rest))))) + (t + (setf (car choices-rest) flattened-choice))) + (setq choices-rest next-choices-rest)))) + (let ((choices (choices alternation))) + (cond ((cadr choices) + alternation) + ((cdr choices) + (first choices)) + (t (signal-ppcre-syntax-error + "Encountered alternation without choices."))))) + +(defmethod flatten ((branch branch)) + (with-slots ((test test) + (then-regex then-regex) + (else-regex else-regex)) + branch + (setq test + (if (numberp test) + test + (flatten test)) + then-regex (flatten then-regex) + else-regex (flatten else-regex)) + branch)) + +(defmethod flatten ((regex regex)) + (typecase regex + ((or repetition register lookahead lookbehind standalone) + ;; if REGEX contains exactly one inner REGEX object flatten it + (setf (regex regex) + (flatten (regex regex))) + regex) + (t + ;; otherwise (ANCHOR, BACK-REFERENCE, CHAR-CLASS, EVERYTHING, + ;; LOOKAHEAD, LOOKBEHIND, STR, VOID, FILTER, and WORD-BOUNDARY) + ;; do nothing + regex))) + +(defgeneric gather-strings (regex) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Collects adjacent strings or characters into one +string provided they have the same case mode. This is a destructive +operation on REGEX.")) + +(defmethod gather-strings ((seq seq)) + ;; note that GATHER-STRINGS is to be applied after FLATTEN, i.e. it + ;; expects SEQ to be flattened already; in particular, SEQ cannot be + ;; empty and cannot contain embedded SEQ objects + (let* ((start-point (cons nil (elements seq))) + (curr-point start-point) + old-case-mode + collector + collector-start + (collector-length 0) + skip) + (declare (type fixnum collector-length)) + (loop + (let ((elements-rest (cdr curr-point))) + (unless elements-rest + (return)) + (let* ((element (car elements-rest)) + (case-mode (case-mode element old-case-mode))) + (cond ((and case-mode + (eq case-mode old-case-mode)) + ;; if ELEMENT is a STR and we have collected a STR of + ;; the same case mode in the last iteration we + ;; concatenate ELEMENT onto COLLECTOR and remember the + ;; value of its SKIP slot + (let ((old-collector-length collector-length)) + (unless (and (adjustable-array-p collector) + (array-has-fill-pointer-p collector)) + (setq collector + (make-array collector-length + :initial-contents collector + :element-type 'character + :fill-pointer t + :adjustable t) + collector-start nil)) + (adjust-array collector + (incf collector-length (len element)) + :fill-pointer t) + (setf (subseq collector + old-collector-length) + (str element) + ;; it suffices to remember the last SKIP slot + ;; because due to the way MAYBE-ACCUMULATE + ;; works adjacent STR objects have the same + ;; SKIP value + skip (skip element))) + (setf (cdr curr-point) (cdr elements-rest))) + (t + (let ((collected-string + (cond (collector-start + collector-start) + (collector + ;; if we have collected something already + ;; we convert it into a STR + (make-instance 'str + :skip skip + :str collector + :case-insensitive-p + (eq old-case-mode + :case-insensitive))) + (t nil)))) + (cond (case-mode + ;; if ELEMENT is a string with a different case + ;; mode than the last one we have either just + ;; converted COLLECTOR into a STR or COLLECTOR + ;; is still empty; in both cases we can now + ;; begin to fill it anew + (setq collector (str element) + collector-start element + ;; and we remember the SKIP value as above + skip (skip element) + collector-length (len element)) + (cond (collected-string + (setf (car elements-rest) + collected-string + curr-point + (cdr curr-point))) + (t + (setf (cdr curr-point) + (cdr elements-rest))))) + (t + ;; otherwise this is not a STR so we apply + ;; GATHER-STRINGS to it and collect it directly + ;; into RESULT + (cond (collected-string + (setf (car elements-rest) + collected-string + curr-point + (cdr curr-point) + (cdr curr-point) + (cons (gather-strings element) + (cdr curr-point)) + curr-point + (cdr curr-point))) + (t + (setf (car elements-rest) + (gather-strings element) + curr-point + (cdr curr-point)))) + ;; we also have to empty COLLECTOR here in case + ;; it was still filled from the last iteration + (setq collector nil + collector-start nil)))))) + (setq old-case-mode case-mode)))) + (when collector + (setf (cdr curr-point) + (cons + (make-instance 'str + :skip skip + :str collector + :case-insensitive-p + (eq old-case-mode + :case-insensitive)) + nil))) + (setf (elements seq) (cdr start-point)) + seq)) + +(defmethod gather-strings ((alternation alternation)) + ;; loop ON the choices of ALTERNATION so we can modify them directly + (loop for choices-rest on (choices alternation) + while choices-rest + do (setf (car choices-rest) + (gather-strings (car choices-rest)))) + alternation) + +(defmethod gather-strings ((branch branch)) + (with-slots ((test test) + (then-regex then-regex) + (else-regex else-regex)) + branch + (setq test + (if (numberp test) + test + (gather-strings test)) + then-regex (gather-strings then-regex) + else-regex (gather-strings else-regex)) + branch)) + +(defmethod gather-strings ((regex regex)) + (typecase regex + ((or repetition register lookahead lookbehind standalone) + ;; if REGEX contains exactly one inner REGEX object apply + ;; GATHER-STRINGS to it + (setf (regex regex) + (gather-strings (regex regex))) + regex) + (t + ;; otherwise (ANCHOR, BACK-REFERENCE, CHAR-CLASS, EVERYTHING, + ;; LOOKAHEAD, LOOKBEHIND, STR, VOID, FILTER, and WORD-BOUNDARY) + ;; do nothing + regex))) + +;; Note that START-ANCHORED-P will be called after FLATTEN and GATHER-STRINGS. + +(defgeneric start-anchored-p (regex &optional in-seq-p) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Returns T if REGEX starts with a \"real\" start +anchor, i.e. one that's not in multi-line mode, NIL otherwise. If +IN-SEQ-P is true the function will return :ZERO-LENGTH if REGEX is a +zero-length assertion.")) + +(defmethod start-anchored-p ((seq seq) &optional in-seq-p) + (declare (ignore in-seq-p)) + ;; note that START-ANCHORED-P is to be applied after FLATTEN and + ;; GATHER-STRINGS, i.e. SEQ cannot be empty and cannot contain + ;; embedded SEQ objects + (loop for element in (elements seq) + for anchored-p = (start-anchored-p element t) + ;; skip zero-length elements because they won't affect the + ;; "anchoredness" of the sequence + while (eq anchored-p :zero-length) + finally (return (and anchored-p (not (eq anchored-p :zero-length)))))) + +(defmethod start-anchored-p ((alternation alternation) &optional in-seq-p) + (declare (ignore in-seq-p)) + ;; clearly an alternation can only be start-anchored if all of its + ;; choices are start-anchored + (loop for choice in (choices alternation) + always (start-anchored-p choice))) + +(defmethod start-anchored-p ((branch branch) &optional in-seq-p) + (declare (ignore in-seq-p)) + (and (start-anchored-p (then-regex branch)) + (start-anchored-p (else-regex branch)))) + +(defmethod start-anchored-p ((repetition repetition) &optional in-seq-p) + (declare (ignore in-seq-p)) + ;; well, this wouldn't make much sense, but anyway... + (and (plusp (minimum repetition)) + (start-anchored-p (regex repetition)))) + +(defmethod start-anchored-p ((register register) &optional in-seq-p) + (declare (ignore in-seq-p)) + (start-anchored-p (regex register))) + +(defmethod start-anchored-p ((standalone standalone) &optional in-seq-p) + (declare (ignore in-seq-p)) + (start-anchored-p (regex standalone))) + +(defmethod start-anchored-p ((anchor anchor) &optional in-seq-p) + (declare (ignore in-seq-p)) + (and (startp anchor) + (not (multi-line-p anchor)))) + +(defmethod start-anchored-p ((regex regex) &optional in-seq-p) + (typecase regex + ((or lookahead lookbehind word-boundary void) + ;; zero-length assertions + (if in-seq-p + :zero-length + nil)) + (filter + (if (and in-seq-p + (len regex) + (zerop (len regex))) + :zero-length + nil)) + (t + ;; BACK-REFERENCE, CHAR-CLASS, EVERYTHING, and STR + nil))) + +;; Note that END-STRING-AUX will be called after FLATTEN and GATHER-STRINGS. + +(defgeneric end-string-aux (regex &optional old-case-insensitive-p) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Returns the constant string (if it exists) REGEX +ends with wrapped into a STR object, otherwise NIL. +OLD-CASE-INSENSITIVE-P is the CASE-INSENSITIVE-P slot of the last STR +collected or :VOID if no STR has been collected yet. (This is a helper +function called by END-STRIN.)")) + +(defmethod end-string-aux ((str str) + &optional (old-case-insensitive-p :void)) + (declare (special last-str)) + (cond ((and (not (skip str)) ; avoid constituents of STARTS-WITH + ;; only use STR if nothing has been collected yet or if + ;; the collected string has the same value for + ;; CASE-INSENSITIVE-P + (or (eq old-case-insensitive-p :void) + (eq (case-insensitive-p str) old-case-insensitive-p))) + (setf last-str str + ;; set the SKIP property of this STR + (skip str) t) + str) + (t nil))) + +(defmethod end-string-aux ((seq seq) + &optional (old-case-insensitive-p :void)) + (declare (special continuep)) + (let (case-insensitive-p + concatenated-string + concatenated-start + (concatenated-length 0)) + (declare (type fixnum concatenated-length)) + (loop for element in (reverse (elements seq)) + ;; remember the case-(in)sensitivity of the last relevant + ;; STR object + for loop-old-case-insensitive-p = old-case-insensitive-p + then (if skip + loop-old-case-insensitive-p + (case-insensitive-p element-end)) + ;; the end-string of the current element + for element-end = (end-string-aux element + loop-old-case-insensitive-p) + ;; whether we encountered a zero-length element + for skip = (if element-end + (zerop (len element-end)) + nil) + ;; set CONTINUEP to NIL if we have to stop collecting to + ;; alert END-STRING-AUX methods on enclosing SEQ objects + unless element-end + do (setq continuep nil) + ;; end loop if we neither got a STR nor a zero-length + ;; element + while element-end + ;; only collect if not zero-length + unless skip + do (cond (concatenated-string + (when concatenated-start + (setf concatenated-string + (make-array concatenated-length + :initial-contents (reverse (str concatenated-start)) + :element-type 'character + :fill-pointer t + :adjustable t) + concatenated-start nil)) + (let ((len (len element-end)) + (str (str element-end))) + (declare (type fixnum len)) + (incf concatenated-length len) + (loop for i of-type fixnum downfrom (1- len) to 0 + do (vector-push-extend (char str i) + concatenated-string)))) + (t + (setf concatenated-string + t + concatenated-start + element-end + concatenated-length + (len element-end) + case-insensitive-p + (case-insensitive-p element-end)))) + ;; stop collecting if END-STRING-AUX on inner SEQ has said so + while continuep) + (cond ((zerop concatenated-length) + ;; don't bother to return zero-length strings + nil) + (concatenated-start + concatenated-start) + (t + (make-instance 'str + :str (nreverse concatenated-string) + :case-insensitive-p case-insensitive-p))))) + +(defmethod end-string-aux ((register register) + &optional (old-case-insensitive-p :void)) + (end-string-aux (regex register) old-case-insensitive-p)) + +(defmethod end-string-aux ((standalone standalone) + &optional (old-case-insensitive-p :void)) + (end-string-aux (regex standalone) old-case-insensitive-p)) + +(defmethod end-string-aux ((regex regex) + &optional (old-case-insensitive-p :void)) + (declare (special last-str end-anchored-p continuep)) + (typecase regex + ((or anchor lookahead lookbehind word-boundary void) + ;; a zero-length REGEX object - for the sake of END-STRING-AUX + ;; this is a zero-length string + (when (and (typep regex 'anchor) + (not (startp regex)) + (or (no-newline-p regex) + (not (multi-line-p regex))) + (eq old-case-insensitive-p :void)) + ;; if this is a "real" end-anchor and we haven't collected + ;; anything so far we can set END-ANCHORED-P (where 1 or 0 + ;; indicate whether we accept a #\Newline at the end or not) + (setq end-anchored-p (if (no-newline-p regex) 0 1))) + (make-instance 'str + :str "" + :case-insensitive-p :void)) + (t + ;; (ALTERNATION, BACK-REFERENCE, BRANCH, CHAR-CLASS, EVERYTHING, + ;; REPETITION, FILTER) + nil))) + +(defmethod end-string ((regex regex)) + (declare (special end-string-offset)) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Returns the constant string (if it exists) REGEX ends with wrapped +into a STR object, otherwise NIL." + ;; LAST-STR points to the last STR object (seen from the end) that's + ;; part of END-STRING; CONTINUEP is set to T if we stop collecting + ;; in the middle of a SEQ + (let ((continuep t) + last-str) + (declare (special continuep last-str)) + (prog1 + (end-string-aux regex) + (when last-str + ;; if we've found something set the START-OF-END-STRING-P of + ;; the leftmost STR collected accordingly and remember the + ;; OFFSET of this STR (in a special variable provided by the + ;; caller of this function) + (setf (start-of-end-string-p last-str) t + end-string-offset (offset last-str)))))) + +(defgeneric compute-min-rest (regex current-min-rest) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Returns the minimal length of REGEX plus +CURRENT-MIN-REST. This is similar to REGEX-MIN-LENGTH except that it +recurses down into REGEX and sets the MIN-REST slots of REPETITION +objects.")) + +(defmethod compute-min-rest ((seq seq) current-min-rest) + (loop for element in (reverse (elements seq)) + for last-min-rest = current-min-rest then this-min-rest + for this-min-rest = (compute-min-rest element last-min-rest) + finally (return this-min-rest))) + +(defmethod compute-min-rest ((alternation alternation) current-min-rest) + (loop for choice in (choices alternation) + minimize (compute-min-rest choice current-min-rest))) + +(defmethod compute-min-rest ((branch branch) current-min-rest) + (min (compute-min-rest (then-regex branch) current-min-rest) + (compute-min-rest (else-regex branch) current-min-rest))) + +(defmethod compute-min-rest ((str str) current-min-rest) + (+ current-min-rest (len str))) + +(defmethod compute-min-rest ((filter filter) current-min-rest) + (+ current-min-rest (or (len filter) 0))) + +(defmethod compute-min-rest ((repetition repetition) current-min-rest) + (setf (min-rest repetition) current-min-rest) + (compute-min-rest (regex repetition) current-min-rest) + (+ current-min-rest (* (minimum repetition) (min-len repetition)))) + +(defmethod compute-min-rest ((register register) current-min-rest) + (compute-min-rest (regex register) current-min-rest)) + +(defmethod compute-min-rest ((standalone standalone) current-min-rest) + (declare (ignore current-min-rest)) + (compute-min-rest (regex standalone) 0)) + +(defmethod compute-min-rest ((lookahead lookahead) current-min-rest) + (compute-min-rest (regex lookahead) 0) + current-min-rest) + +(defmethod compute-min-rest ((lookbehind lookbehind) current-min-rest) + (compute-min-rest (regex lookbehind) (+ current-min-rest (len lookbehind))) + current-min-rest) + +(defmethod compute-min-rest ((regex regex) current-min-rest) + (typecase regex + ((or char-class everything) + (1+ current-min-rest)) + (t + ;; zero min-len and no embedded regexes (ANCHOR, + ;; BACK-REFERENCE, VOID, and WORD-BOUNDARY) + current-min-rest))) diff --git a/practicals/libraries/cl-ppcre-1.2.3/packages.lisp b/practicals/libraries/cl-ppcre-1.2.3/packages.lisp new file mode 100644 index 0000000..2cecea8 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/packages.lisp @@ -0,0 +1,104 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/packages.lisp,v 1.17 2004/09/30 09:58:42 edi Exp $ + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :cl-user) + +#-:cormanlisp +(defpackage #:cl-ppcre + (:nicknames #:ppcre) + #+genera (:shadowing-import-from #:common-lisp #:lambda #:simple-string #:string) + (:use #-genera #:cl #+genera #:future-common-lisp) + (:export #:create-scanner + #:parse-tree-synonym + #:define-parse-tree-synonym + #:scan + #:scan-to-strings + #:do-scans + #:do-matches + #:do-matches-as-strings + #:all-matches + #:all-matches-as-strings + #:split + #:regex-replace + #:regex-replace-all + #:regex-apropos + #:regex-apropos-list + #:quote-meta-chars + #:*regex-char-code-limit* + #:*use-bmh-matchers* + #:*allow-quoting* + #:ppcre-error + #:ppcre-invocation-error + #:ppcre-syntax-error + #:ppcre-syntax-error-string + #:ppcre-syntax-error-pos + #:register-groups-bind + #:do-register-groups)) + +#+:cormanlisp +(defpackage "CL-PPCRE" + (:nicknames "PPCRE") + (:use "CL") + (:export "CREATE-SCANNER" + "PARSE-TREE-SYNONYM" + "DEFINE-PARSE-TREE-SYNONYM" + "SCAN" + "SCAN-TO-STRINGS" + "DO-SCANS" + "DO-MATCHES" + "DO-MATCHES-AS-STRINGS" + "ALL-MATCHES" + "ALL-MATCHES-AS-STRINGS" + "SPLIT" + "REGEX-REPLACE" + "REGEX-REPLACE-ALL" + "REGEX-APROPOS" + "REGEX-APROPOS-LIST" + "QUOTE-META-CHARS" + "*REGEX-CHAR-CODE-LIMIT*" + "*USE-BMH-MATCHERS*" + "*ALLOW-QUOTING*" + "PPCRE-ERROR" + "PPCRE-INVOCATION-ERROR" + "PPCRE-SYNTAX-ERROR" + "PPCRE-SYNTAX-ERROR-STRING" + "PPCRE-SYNTAX-ERROR-POS" + "REGISTER-GROUPS-BIND" + "DO-REGISTER-GROUPS")) + +#-:cormanlisp +(defpackage #:cl-ppcre-test + #+genera (:shadowing-import-from #:common-lisp #:lambda) + (:use #-genera #:cl #+genera #:future-common-lisp #:cl-ppcre) + (:export #:test)) + +#+:cormanlisp +(defpackage "CL-PPCRE-TEST" + (:use "CL" "CL-PPCRE") + (:export "TEST")) diff --git a/practicals/libraries/cl-ppcre-1.2.3/parser.lisp b/practicals/libraries/cl-ppcre-1.2.3/parser.lisp new file mode 100644 index 0000000..559869f --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/parser.lisp @@ -0,0 +1,347 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/parser.lisp,v 1.17 2004/04/20 11:37:36 edi Exp $ + +;;; The parser will - with the help of the lexer - parse a regex +;;; string and convert it into a "parse tree" (see docs for details +;;; about the syntax of these trees). Note that the lexer might return +;;; illegal parse trees. It is assumed that the conversion process +;;; later on will track them down. + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre) + +(defun group (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Parses and consumes a . +The productions are: -> \"(\"\")\" + \"(?:\"\")\" + \"(?<\"\")\" + \"(?:\"\")\" + \"(?=\"\")\" + \"(?!\"\")\" + \"(?<=\"\")\" + \"(?\")\" + \"(?(\"\")\"\")\" + \"(?(\"\")\"\")\" + +where is parsed by the lexer function MAYBE-PARSE-FLAGS. +Will return or ( ) where + is one of six keywords - see source for details." + (multiple-value-bind (open-token flags) + (get-token lexer) + (cond ((eq open-token :open-paren-paren) + ;; special case for conditional regular expressions; note + ;; that at this point we accept a couple of illegal + ;; combinations which'll be sorted out later by the + ;; converter + (let* ((open-paren-pos (car (lexer-last-pos lexer))) + ;; check if what follows "(?(" is a number + (number (try-number lexer :no-whitespace-p t)) + ;; make changes to extended-mode-p local + (*extended-mode-p* *extended-mode-p*)) + (declare (type fixnum open-paren-pos)) + (cond (number + ;; condition is a number (i.e. refers to a + ;; back-reference) + (let* ((inner-close-token (get-token lexer)) + (reg-expr (reg-expr lexer)) + (close-token (get-token lexer))) + (unless (eq inner-close-token :close-paren) + (signal-ppcre-syntax-error* + (+ open-paren-pos 2) + "Opening paren has no matching closing paren")) + (unless (eq close-token :close-paren) + (signal-ppcre-syntax-error* + open-paren-pos + "Opening paren has no matching closing paren")) + (list :branch number reg-expr))) + (t + ;; condition must be a full regex (actually a + ;; look-behind or look-ahead); and here comes a + ;; terrible kludge: instead of being cleanly + ;; separated from the lexer, the parser pushes + ;; back the lexer by one position, thereby + ;; landing in the middle of the 'token' "(?(" - + ;; yuck!! + (decf (lexer-pos lexer)) + (let* ((inner-reg-expr (group lexer)) + (reg-expr (reg-expr lexer)) + (close-token (get-token lexer))) + (unless (eq close-token :close-paren) + (signal-ppcre-syntax-error* + open-paren-pos + "Opening paren has no matching closing paren")) + (list :branch inner-reg-expr reg-expr)))))) + ((member open-token '(:open-paren + :open-paren-colon + :open-paren-greater + :open-paren-equal + :open-paren-exclamation + :open-paren-less-equal + :open-paren-less-exclamation) + :test #'eq) + ;; make changes to extended-mode-p local + (let ((*extended-mode-p* *extended-mode-p*)) + ;; we saw one of the six token representing opening + ;; parentheses + (let* ((open-paren-pos (car (lexer-last-pos lexer))) + (reg-expr (reg-expr lexer)) + (close-token (get-token lexer))) + (when (eq open-token :open-paren) + ;; if this is the "("")" production we have to + ;; increment the register counter of the lexer + (incf (lexer-reg lexer))) + (unless (eq close-token :close-paren) + ;; the token following must be the closing + ;; parenthesis or this is a syntax error + (signal-ppcre-syntax-error* + open-paren-pos + "Opening paren has no matching closing paren")) + (if flags + ;; if the lexer has returned a list of flags this must + ;; have been the "(?:"")" production + (cons :group (nconc flags (list reg-expr))) + (list (case open-token + ((:open-paren) + :register) + ((:open-paren-colon) + :group) + ((:open-paren-greater) + :standalone) + ((:open-paren-equal) + :positive-lookahead) + ((:open-paren-exclamation) + :negative-lookahead) + ((:open-paren-less-equal) + :positive-lookbehind) + ((:open-paren-less-exclamation) + :negative-lookbehind)) + reg-expr))))) + (t + ;; this is the production; is + ;; any token which passes START-OF-SUBEXPR-P (otherwise + ;; parsing had already stopped in the SEQ method) + open-token)))) + +(defun greedy-quant (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Parses and consumes a . +The productions are: -> | +where is parsed by the lexer function GET-QUANTIFIER. +Will return or (:GREEDY-REPETITION )." + (let* ((group (group lexer)) + (token (get-quantifier lexer))) + (if token + ;; if GET-QUANTIFIER returned a non-NIL value it's the + ;; two-element list ( ) + (list :greedy-repetition (first token) (second token) group) + group))) + +(defun quant (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Parses and consumes a . +The productions are: -> | \"?\". +Will return the returned by GREEDY-QUANT and optionally +change :GREEDY-REPETITION to :NON-GREEDY-REPETITION." + (let* ((greedy-quant (greedy-quant lexer)) + (pos (lexer-pos lexer)) + (next-char (next-char lexer))) + (when next-char + (if (char= next-char #\?) + (setf (car greedy-quant) :non-greedy-repetition) + (setf (lexer-pos lexer) pos))) + greedy-quant)) + +(defun seq (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Parses and consumes a . +The productions are: -> | . +Will return or (:SEQUENCE )." + (flet ((make-array-from-two-chars (char1 char2) + (let ((string (make-array 2 + :element-type 'character + :fill-pointer t + :adjustable t))) + (setf (aref string 0) char1) + (setf (aref string 1) char2) + string))) + ;; Note that we're calling START-OF-SUBEXPR-P before we actually try + ;; to parse a or in order to catch empty regular + ;; expressions + (if (start-of-subexpr-p lexer) + (let ((quant (quant lexer))) + (if (start-of-subexpr-p lexer) + (let* ((seq (seq lexer)) + (quant-is-char-p (characterp quant)) + (seq-is-sequence-p (and (consp seq) + (eq (first seq) :sequence)))) + (cond ((and quant-is-char-p + (characterp seq)) + (make-array-from-two-chars seq quant)) + ((and quant-is-char-p + (stringp seq)) + (vector-push-extend quant seq) + seq) + ((and quant-is-char-p + seq-is-sequence-p + (characterp (second seq))) + (cond ((cddr seq) + (setf (cdr seq) + (cons + (make-array-from-two-chars (second seq) + quant) + (cddr seq))) + seq) + (t (make-array-from-two-chars (second seq) quant)))) + ((and quant-is-char-p + seq-is-sequence-p + (stringp (second seq))) + (cond ((cddr seq) + (setf (cdr seq) + (cons + (progn + (vector-push-extend quant (second seq)) + (second seq)) + (cddr seq))) + seq) + (t + (vector-push-extend quant (second seq)) + (second seq)))) + (seq-is-sequence-p + ;; if is also a :SEQUENCE parse tree we merge + ;; both lists into one to avoid unnecessary consing + (setf (cdr seq) + (cons quant (cdr seq))) + seq) + (t (list :sequence quant seq)))) + quant)) + :void))) + +(defun reg-expr (lexer) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Parses and consumes a , a complete regular expression. +The productions are: -> | \"|\". +Will return or (:ALTERNATION )." + (let ((pos (lexer-pos lexer))) + (case (next-char lexer) + ((nil) + ;; if we didn't get any token we return :VOID which stands for + ;; "empty regular expression" + :void) + ((#\|) + ;; now check whether the expression started with a vertical + ;; bar, i.e. - the left alternation - is empty + (list :alternation :void (reg-expr lexer))) + (otherwise + ;; otherwise un-read the character we just saw and parse a + ;; plus the character following it + (setf (lexer-pos lexer) pos) + (let* ((seq (seq lexer)) + (pos (lexer-pos lexer))) + (case (next-char lexer) + ((nil) + ;; no further character, just a + seq) + ((#\|) + ;; if the character was a vertical bar, this is an + ;; alternation and we have the second production + (let ((reg-expr (reg-expr lexer))) + (cond ((and (consp reg-expr) + (eq (first reg-expr) :alternation)) + ;; again we try to merge as above in SEQ + (setf (cdr reg-expr) + (cons seq (cdr reg-expr))) + reg-expr) + (t (list :alternation seq reg-expr))))) + (otherwise + ;; a character which is not a vertical bar - this is + ;; either a syntax error or we're inside of a group and + ;; the next character is a closing parenthesis; so we + ;; just un-read the character and let another function + ;; take care of it + (setf (lexer-pos lexer) pos) + seq))))))) + +(defun reverse-strings (parse-tree) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (cond ((stringp parse-tree) + (nreverse parse-tree)) + ((consp parse-tree) + (loop for parse-tree-rest on parse-tree + while parse-tree-rest + do (setf (car parse-tree-rest) + (reverse-strings (car parse-tree-rest)))) + parse-tree) + (t parse-tree))) + +(defun parse-string (string) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Translate the regex string STRING into a parse tree." + (let* ((lexer (make-lexer string)) + (parse-tree (reverse-strings (reg-expr lexer)))) + ;; check whether we've consumed the whole regex string + (if (end-of-string-p lexer) + parse-tree + (signal-ppcre-syntax-error* + (lexer-pos lexer) + "Expected end of string")))) \ No newline at end of file diff --git a/practicals/libraries/cl-ppcre-1.2.3/perltest.pl b/practicals/libraries/cl-ppcre-1.2.3/perltest.pl new file mode 100644 index 0000000..8e79287 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/perltest.pl @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +# This is a heavily modified version of the file 'perltest' which +# comes with the PCRE library package, which is open source software, +# written by Philip Hazel, and copyright by the University of +# Cambridge, England. + +# The PCRE library package is available from +# + +use Time::HiRes qw(time); + +sub string_for_lisp { + my(@a, $t, $in_string, $switch); + + my $string = shift; + $string =~ s/\\/\\\\/g; + $string =~ s/"/\\"/g; + + return "\"$string\"" + if $string =~ /^[\n\x20-\x7f]*$/; + + $in_string = 1; + foreach $c (split(//, $string)) { + if (ord $c >= 32 and ord $c < 127) { + if ($in_string) { + $t .= $c; + } else { + $in_string = 1; + $t = $c; + } + } else { + if ($in_string) { + push @a, "\"$t\""; + $in_string = 0; + $switch = 1; + } + push @a, ord $c; + } + } + if ($switch) { + if ($in_string) { + push @a, "\"$t\""; + } + '(' . (join ' ', @a) . ')'; + } else { + "\"$t\""; + } +} + +$min_time = shift; + +NEXT_RE: while (1) { + last + if !($_ = <>); + next + if $_ eq ""; + + $pattern = $_; + + while ($pattern !~ /^\s*(.).*\1/s) { + last + if !($_ = <>); + $pattern .= $_; + } + + chomp($pattern); + $pattern =~ s/\s+$//; + $pattern =~ s/\+(?=[a-z]*$)//; + + $multi_line_mode = ($pattern =~ /m[a-z]*$/) ? 't' : 'nil'; + $single_line_mode = ($pattern =~ /s[a-z]*$/) ? 't' : 'nil'; + $extended_mode = ($pattern =~ /x[a-z]*$/) ? 't' : 'nil'; + $case_insensitive_mode = ($pattern =~ /i[a-z]*$/) ? 't' : 'nil'; + $pattern =~ s/^(.*)g([a-z]*)$/\1\2/; + + $pattern_for_lisp = $pattern; + $pattern_for_lisp =~ s/[a-z]*$//; + $pattern_for_lisp =~ s/^\s*(.)(.*)\1/$2/s; + $pattern_for_lisp =~ s/\\/\\\\/g; + $pattern_for_lisp =~ s/"/\\"/g; + + $pattern = "/(?#)/$2" + if ($pattern =~ /^(.)\1(.*)$/); + + while (1) { + last NEXT_RE + if !($_ = <>); + + chomp; + + s/\s+$//; + s/^\s+//; + + last + if ($_ eq ""); + + $info_string = string_for_lisp "\"$_\" =~ $pattern"; + $x = eval "\"$_\""; + + @subs = (); + + eval <<"END"; +if (\$x =~ ${pattern}) { + push \@subs,\$&; + push \@subs,\$1; + push \@subs,\$2; + push \@subs,\$3; + push \@subs,\$4; + push \@subs,\$5; + push \@subs,\$6; + push \@subs,\$7; + push \@subs,\$8; + push \@subs,\$9; + push \@subs,\$10; + push \@subs,\$11; + push \@subs,\$12; + push \@subs,\$13; + push \@subs,\$14; + push \@subs,\$15; + push \@subs,\$16; +} + +\$test = sub { + my \$times = shift; + + my \$start = time; + for (my \$i = 0; \$i < \$times; \$i++) { + \$x =~ ${pattern}; + } + return time - \$start; +}; +END + + $times = 1; + $used = 0; + $counter++; + print STDERR "$counter\n"; + + if ($@) { + $error = 't'; + } else { + $error = 'nil'; + if ($min_time) { + $times = 10; + while (1) { + $used = &$test($times); + last + if $used > $min_time; + $times *= 10; + } + } + } + + print "($counter $info_string \"$pattern_for_lisp\" $case_insensitive_mode $multi_line_mode $single_line_mode $extended_mode " . string_for_lisp($x) . " $error $times $used "; + if (!@subs) { + print 'nil nil'; + } else { + print string_for_lisp($subs[0]) . ' ('; + undef $not_first; + for ($i = 1; $i <= 16; $i++) { + print ' ' + unless $i == 1; + if (defined $subs[$i]) { + print string_for_lisp $subs[$i]; + } else { + print 'nil'; + } + } + print ')'; + } + print ")\n"; + } +} diff --git a/practicals/libraries/cl-ppcre-1.2.3/ppcre-tests.lisp b/practicals/libraries/cl-ppcre-1.2.3/ppcre-tests.lisp new file mode 100644 index 0000000..b419914 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/ppcre-tests.lisp @@ -0,0 +1,284 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE-TEST; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/ppcre-tests.lisp,v 1.26 2004/09/30 09:58:42 edi Exp $ + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre-test) + +(defparameter *cl-ppcre-test-base-directory* + (make-pathname :name nil :type nil :version nil + :defaults (parse-namestring *load-truename*))) + +(defun full-gc () + "Start a full garbage collection." + ;; what are the corresponding values for MCL and OpenMCL? + #+:allegro (excl:gc t) + #+(or :cmu :scl) (ext:gc :full t) + #+:ecl (si:gc t) + #+:clisp (ext:gc) + #+:cormanlisp (loop for i from 0 to 3 do (cormanlisp:gc i)) + #+:lispworks (hcl:mark-and-sweep 3) + #+:sbcl (sb-ext:gc :full t)) + +;; warning: ugly code ahead!! +;; this is just a quick hack for testing purposes + +(defun time-regex (factor regex string + &key case-insensitive-mode + multi-line-mode + single-line-mode + extended-mode) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Auxiliary function used by TEST to benchmark a regex scanner +against Perl timings." + (declare (type string string)) + (let* ((scanner (create-scanner regex + :case-insensitive-mode case-insensitive-mode + :multi-line-mode multi-line-mode + :single-line-mode single-line-mode + :extended-mode extended-mode)) + ;; make sure GC doesn't invalidate our benchmarking + (dummy (full-gc)) + (start (get-internal-real-time))) + (declare (ignore dummy)) + (dotimes (i factor) + (funcall scanner string 0 (length string))) + (float (/ (- (get-internal-real-time) start) internal-time-units-per-second)))) + +#+(or scl + lispworks + (and sbcl sb-thread)) +(defun threaded-scan (scanner target-string &key (threads 10) (repetitions 5000)) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Auxiliary function used by TEST to check whether SCANNER is thread-safe." + (full-gc) + (let ((collector (make-array threads)) + (counter 0)) + (loop for i below threads + do (let* ((j i) + (fn + (lambda () + (let ((r (random repetitions))) + (loop for k below repetitions + if (= k r) + do (setf (aref collector j) + (let ((result + (multiple-value-list + (cl-ppcre:scan scanner target-string)))) + (unless (cdr result) + (setq result '(nil nil #() #()))) + result)) + else + do (cl-ppcre:scan scanner target-string)) + (incf counter))))) + #+scl (thread:thread-create fn) + #+lispworks (mp:process-run-function "" nil fn) + #+(and sbcl sb-thread) (sb-thread:make-thread fn))) + (loop while (< counter threads) + do (sleep .1)) + (destructuring-bind (first-start first-end first-reg-starts first-reg-ends) + (aref collector 0) + (loop for (start end reg-starts reg-ends) across collector + if (or (not (eql first-start start)) + (not (eql first-end end)) + (/= (length first-reg-starts) (length reg-starts)) + (/= (length first-reg-ends) (length reg-ends)) + (loop for first-reg-start across first-reg-starts + for reg-start across reg-starts + thereis (not (eql first-reg-start reg-start))) + (loop for first-reg-end across first-reg-ends + for reg-end across reg-ends + thereis (not (eql first-reg-end reg-end)))) + do (return (format nil "~&Inconsistent results during multi-threading")))))) + +(defun create-string-from-input (input) + (cond ((or (null input) + (stringp input)) + input) + (t + (cl-ppcre::string-list-to-simple-string + (loop for element in input + if (stringp element) + collect element + else + collect (string (code-char element))))))) + +(defun test (&key (file-name + (make-pathname :name "testdata" + :type nil :version nil + :defaults *cl-ppcre-test-base-directory*) + file-name-provided-p) + threaded) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (ignorable threaded)) + "Loop through all test cases in FILE-NAME and print report. Only in +LispWorks and SCL: If THREADED is true, also test whether the scanners +work multi-threaded." + (with-open-file (stream file-name + #+(or :allegro :clisp :scl) + :external-format + #+(or :allegro :clisp :scl) + (if file-name-provided-p + :default + #+:allegro :iso-8859-1 + #+:clisp charset:iso-8859-1 + #+:scl :iso-8859-1)) + (loop with testcount of-type fixnum = 0 + with *regex-char-code-limit* = (if file-name-provided-p + *regex-char-code-limit* + ;; the standard test suite + ;; doesn't need full + ;; Unicode support + 255) + with *allow-quoting* = (if file-name-provided-p + *allow-quoting* + t) + for input-line = (read stream nil nil) + for (counter info-string regex + case-insensitive-mode multi-line-mode + single-line-mode extended-mode + string perl-error factor + perl-time ex-result ex-subs) = input-line + while input-line + do (let ((info-string (create-string-from-input info-string)) + (regex (create-string-from-input regex)) + (string (create-string-from-input string)) + (ex-result (create-string-from-input ex-result)) + (ex-subs (mapcar #'create-string-from-input ex-subs)) + (errors '())) + ;; provide some visual feedback for slow CL + ;; implementations; suggested by JP Massar + (incf testcount) + #+(or scl + lispworks + (and sbcl sb-thread)) + (when threaded + (format t "Test #~A (ID ~A)~%" testcount counter) + (force-output)) + (unless #-(or scl + lispworks + (and sbcl sb-thread)) + nil + #+(or scl + lispworks + (and sbcl sb-thread)) + threaded + (when (zerop (mod testcount 10)) + (format t ".") + (force-output)) + (when (zerop (mod testcount 100)) + (terpri))) + (handler-case + (let* ((*use-bmh-matchers* (if (and (> factor 1) (plusp perl-time)) + *use-bmh-matchers* + ;; if we only check for + ;; correctness we don't + ;; care about speed that + ;; match (but rather + ;; about space + ;; constraints of the + ;; trial versions) + nil)) + (scanner (create-scanner regex + :case-insensitive-mode case-insensitive-mode + :multi-line-mode multi-line-mode + :single-line-mode single-line-mode + :extended-mode extended-mode))) + (multiple-value-bind (result1 result2 sub-starts sub-ends) + (scan scanner string) + (cond (perl-error + (push (format nil + "~&expected an error but got a result") + errors)) + (t + (when (not (eq result1 ex-result)) + (if result1 + (let ((result (subseq string result1 result2))) + (unless (string= result ex-result) + (push (format nil + "~&expected ~S but got ~S" + ex-result result) + errors)) + (setq sub-starts (coerce sub-starts 'list) + sub-ends (coerce sub-ends 'list)) + (loop for i from 0 + for ex-sub in ex-subs + for sub-start = (nth i sub-starts) + for sub-end = (nth i sub-ends) + for sub = (if (and sub-start sub-end) + (subseq string sub-start sub-end) + nil) + unless (string= ex-sub sub) + do (push (format nil + "~&\\~A: expected ~S but got ~S" + (1+ i) ex-sub sub) errors))) + (push (format nil + "~&expected ~S but got ~S" + ex-result result1) + errors))))) + #+(or scl + lispworks + (and sbcl sb-thread)) + (when threaded + (let ((thread-result (threaded-scan scanner string))) + (when thread-result + (push thread-result errors)))))) + (condition (msg) + (unless perl-error + (push (format nil "~&got an unexpected error: '~A'" msg) + errors)))) + (setq errors (nreverse errors)) + (cond (errors + (when (or (<= factor 1) (zerop perl-time)) + (format t "~&~4@A (~A):~{~& ~A~}~%" + counter info-string errors))) + ((and (> factor 1) (plusp perl-time)) + (let ((result (time-regex factor regex string + :case-insensitive-mode case-insensitive-mode + :multi-line-mode multi-line-mode + :single-line-mode single-line-mode + :extended-mode extended-mode))) + (format t "~&~4@A: ~,4F (~A repetitions, Perl: ~,4F seconds, CL-PPCRE: ~,4F seconds)" counter + (float (/ result perl-time)) factor perl-time result) + #+:cormanlisp (force-output *standard-output*))) + (t nil)))) + (values))) diff --git a/practicals/libraries/cl-ppcre-1.2.3/regex-class.lisp b/practicals/libraries/cl-ppcre-1.2.3/regex-class.lisp new file mode 100644 index 0000000..247f4fd --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/regex-class.lisp @@ -0,0 +1,809 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/regex-class.lisp,v 1.21 2005/02/02 17:47:38 edi Exp $ + +;;; This file defines the REGEX class and some utility methods for +;;; this class. REGEX objects are used to represent the (transformed) +;;; parse trees internally + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre) + +;; Genera need the eval-when, here, or the types created by the class +;; definitions aren't seen by the typep calls later in the file. +(eval-when (:compile-toplevel :load-toplevel :execute) + (locally + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (defclass regex () + () + (:documentation "The REGEX base class. All other classes inherit +from this one.")) + + + (defclass seq (regex) + ((elements :initarg :elements + :accessor elements + :type cons + :documentation "A list of REGEX objects.")) + (:documentation "SEQ objects represents sequences of +regexes. (Like \"ab\" is the sequence of \"a\" and \"b\".)")) + + (defclass alternation (regex) + ((choices :initarg :choices + :accessor choices + :type cons + :documentation "A list of REGEX objects")) + (:documentation "ALTERNATION objects represent alternations of +regexes. (Like \"a|b\" ist the alternation of \"a\" or \"b\".)")) + + (defclass lookahead (regex) + ((regex :initarg :regex + :accessor regex + :documentation "The REGEX object we're checking.") + (positivep :initarg :positivep + :reader positivep + :documentation "Whether this assertion is positive.")) + (:documentation "LOOKAHEAD objects represent look-ahead assertions.")) + + (defclass lookbehind (regex) + ((regex :initarg :regex + :accessor regex + :documentation "The REGEX object we're checking.") + (positivep :initarg :positivep + :reader positivep + :documentation "Whether this assertion is positive.") + (len :initarg :len + :accessor len + :type fixnum + :documentation "The (fixed) length of the enclosed regex.")) + (:documentation "LOOKBEHIND objects represent look-behind assertions.")) + + (defclass repetition (regex) + ((regex :initarg :regex + :accessor regex + :documentation "The REGEX that's repeated.") + (greedyp :initarg :greedyp + :reader greedyp + :documentation "Whether the repetition is greedy.") + (minimum :initarg :minimum + :accessor minimum + :type fixnum + :documentation "The minimal number of repetitions.") + (maximum :initarg :maximum + :accessor maximum + :documentation "The maximal number of repetitions. +Can be NIL for unbounded.") + (min-len :initarg :min-len + :reader min-len + :documentation "The minimal length of the enclosed regex.") + (len :initarg :len + :reader len + :documentation "The length of the enclosed regex. NIL +if unknown.") + (min-rest :initform 0 + :accessor min-rest + :type fixnum + :documentation "The minimal number of characters which must +appear after this repetition.") + (contains-register-p :initarg :contains-register-p + :reader contains-register-p + :documentation "If the regex contains a register.")) + (:documentation "REPETITION objects represent repetitions of regexes.")) + + (defclass register (regex) + ((regex :initarg :regex + :accessor regex + :documentation "The inner regex.") + (num :initarg :num + :reader num + :type fixnum + :documentation "The number of this register, starting from 0. +This is the index into *REGS-START* and *REGS-END*.")) + (:documentation "REGISTER objects represent register groups.")) + + (defclass standalone (regex) + ((regex :initarg :regex + :accessor regex + :documentation "The inner regex.")) + (:documentation "A standalone regular expression.")) + + (defclass back-reference (regex) + ((num :initarg :num + :accessor num + :type fixnum + :documentation "The number of the register this +reference refers to.") + (case-insensitive-p :initarg :case-insensitive-p + :reader case-insensitive-p + :documentation "Whether we check +case-insensitively.")) + (:documentation "BACK-REFERENCE objects represent backreferences.")) + + (defclass char-class (regex) + ((hash :initarg :hash + :reader hash + :type (or hash-table null) + :documentation "A hash table the keys of which are the +characters; the values are always T.") + (case-insensitive-p :initarg :case-insensitive-p + :reader case-insensitive-p + :documentation "If the char class +case-insensitive.") + (invertedp :initarg :invertedp + :reader invertedp + :documentation "Whether we mean the inverse of +the char class.") + (word-char-class-p :initarg :word-char-class-p + :reader word-char-class-p + :documentation "Whether this CHAR CLASS +represents the special class WORD-CHAR-CLASS.")) + (:documentation "CHAR-CLASS objects represent character classes.")) + + (defclass str (regex) + ((str :initarg :str + :accessor str + :type string + :documentation "The actual string.") + (len :initform 0 + :accessor len + :type fixnum + :documentation "The length of the string.") + (case-insensitive-p :initarg :case-insensitive-p + :reader case-insensitive-p + :documentation "If we match case-insensitively.") + (offset :initform nil + :accessor offset + :documentation "Offset from the left of the whole +parse tree. The first regex has offset 0. NIL if unknown, i.e. behind +a variable-length regex.") + (skip :initform nil + :initarg :skip + :accessor skip + :documentation "If we can avoid testing for this +string because the SCAN function has done this already.") + (start-of-end-string-p :initform nil + :accessor start-of-end-string-p + :documentation "If this is the unique +STR which starts END-STRING (a slot of MATCHER).")) + (:documentation "STR objects represent string.")) + + (defclass anchor (regex) + ((startp :initarg :startp + :reader startp + :documentation "Whether this is a \"start anchor\".") + (multi-line-p :initarg :multi-line-p + :reader multi-line-p + :documentation "Whether we're in multi-line mode, +i.e. whether each #\\Newline is surrounded by anchors.") + (no-newline-p :initarg :no-newline-p + :reader no-newline-p + :documentation "Whether we ignore #\\Newline at the end.")) + (:documentation "ANCHOR objects represent anchors like \"^\" or \"$\".")) + + (defclass everything (regex) + ((single-line-p :initarg :single-line-p + :reader single-line-p + :documentation "Whether we're in single-line mode, +i.e. whether we also match #\\Newline.")) + (:documentation "EVERYTHING objects represent regexes matching +\"everything\", i.e. dots.")) + + (defclass word-boundary (regex) + ((negatedp :initarg :negatedp + :reader negatedp + :documentation "Whether we mean the opposite, +i.e. no word-boundary.")) + (:documentation "WORD-BOUNDARY objects represent word-boundary assertions.")) + + (defclass branch (regex) + ((test :initarg :test + :accessor test + :documentation "The test of this branch, one of +LOOKAHEAD, LOOKBEHIND, or a number.") + (then-regex :initarg :then-regex + :accessor then-regex + :documentation "The regex that's to be matched if the +test succeeds.") + (else-regex :initarg :else-regex + :initform (make-instance 'void) + :accessor else-regex + :documentation "The regex that's to be matched if the +test fails.")) + (:documentation "BRANCH objects represent Perl's conditional regular +expressions.")) + + (defclass filter (regex) + ((fn :initarg :fn + :accessor fn + :type (or function symbol) + :documentation "The user-defined function.") + (len :initarg :len + :reader len + :documentation "The fixed length of this filter or NIL.")) + (:documentation "FILTER objects represent arbitrary functions +defined by the user.")) + + (defclass void (regex) + () + (:documentation "VOID objects represent empty regular expressions.")))) + +(defmethod initialize-instance :after ((char-class char-class) &rest init-args) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Make large hash tables smaller, if possible." + (let ((hash (getf init-args :hash))) + (when (and hash + (> *regex-char-code-limit* 256) + (> (hash-table-count hash) + (/ *regex-char-code-limit* 2))) + (setf (slot-value char-class 'hash) + (merge-inverted-hash (make-hash-table) + hash) + (slot-value char-class 'invertedp) + (not (slot-value char-class 'invertedp)))))) + +(declaim (ftype (function (t) simple-string) str)) + +;;; The following four methods allow a VOID object to behave like a +;;; zero-length STR object (only readers needed) + +(defmethod initialize-instance :after ((str str) &rest init-args) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (ignore init-args)) + "Automatically computes the length of a STR after initialization." + (let ((str-slot (slot-value str 'str))) + (unless (typep str-slot 'simple-string) + (setf (slot-value str 'str) (coerce str-slot 'simple-string)))) + (setf (len str) (length (str str)))) + +(defmethod len ((void void)) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + 0) + +(defmethod str ((void void)) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "") + +(defmethod skip ((void void)) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + nil) + +(defmethod start-of-end-string-p ((void void)) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + nil) + +(defgeneric case-mode (regex old-case-mode) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Utility function used by the optimizer (see GATHER-STRINGS). +Returns a keyword denoting the case-(in)sensitivity of a STR or its +second argument if the STR has length 0. Returns NIL for REGEX objects +which are not of type STR.")) + +(defmethod case-mode ((str str) old-case-mode) + (cond ((zerop (len str)) + old-case-mode) + ((case-insensitive-p str) + :case-insensitive) + (t + :case-sensitive))) + +(defmethod case-mode ((regex regex) old-case-mode) + (declare (ignore old-case-mode)) + nil) + +(defgeneric copy-regex (regex) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Implements a deep copy of a REGEX object.")) + +(defmethod copy-regex ((anchor anchor)) + (make-instance 'anchor + :startp (startp anchor) + :multi-line-p (multi-line-p anchor) + :no-newline-p (no-newline-p anchor))) + +(defmethod copy-regex ((everything everything)) + (make-instance 'everything + :single-line-p (single-line-p everything))) + +(defmethod copy-regex ((word-boundary word-boundary)) + (make-instance 'word-boundary + :negatedp (negatedp word-boundary))) + +(defmethod copy-regex ((void void)) + (make-instance 'void)) + +(defmethod copy-regex ((lookahead lookahead)) + (make-instance 'lookahead + :regex (copy-regex (regex lookahead)) + :positivep (positivep lookahead))) + +(defmethod copy-regex ((seq seq)) + (make-instance 'seq + :elements (mapcar #'copy-regex (elements seq)))) + +(defmethod copy-regex ((alternation alternation)) + (make-instance 'alternation + :choices (mapcar #'copy-regex (choices alternation)))) + +(defmethod copy-regex ((branch branch)) + (with-slots ((test test)) + branch + (make-instance 'branch + :test (if (typep test 'regex) + (copy-regex test) + test) + :then-regex (copy-regex (then-regex branch)) + :else-regex (copy-regex (else-regex branch))))) + +(defmethod copy-regex ((lookbehind lookbehind)) + (make-instance 'lookbehind + :regex (copy-regex (regex lookbehind)) + :positivep (positivep lookbehind) + :len (len lookbehind))) + +(defmethod copy-regex ((repetition repetition)) + (make-instance 'repetition + :regex (copy-regex (regex repetition)) + :greedyp (greedyp repetition) + :minimum (minimum repetition) + :maximum (maximum repetition) + :min-len (min-len repetition) + :len (len repetition) + :contains-register-p (contains-register-p repetition))) + +(defmethod copy-regex ((register register)) + (make-instance 'register + :regex (copy-regex (regex register)) + :num (num register))) + +(defmethod copy-regex ((standalone standalone)) + (make-instance 'standalone + :regex (copy-regex (regex standalone)))) + +(defmethod copy-regex ((back-reference back-reference)) + (make-instance 'back-reference + :num (num back-reference) + :case-insensitive-p (case-insensitive-p back-reference))) + +(defmethod copy-regex ((char-class char-class)) + (make-instance 'char-class + :hash (hash char-class) + :case-insensitive-p (case-insensitive-p char-class) + :invertedp (invertedp char-class) + :word-char-class-p (word-char-class-p char-class))) + +(defmethod copy-regex ((str str)) + (make-instance 'str + :str (str str) + :case-insensitive-p (case-insensitive-p str))) + +(defmethod copy-regex ((filter filter)) + (make-instance 'filter + :fn (fn filter) + :len (len filter))) + +;;; Note that COPY-REGEX and REMOVE-REGISTERS could have easily been +;;; wrapped into one function. Maybe in the next release... + +;;; Further note that this function is used by CONVERT to factor out +;;; complicated repetitions, i.e. cases like +;;; (a)* -> (?:a*(a))? +;;; This won't work for, say, +;;; ((a)|(b))* -> (?:(?:a|b)*((a)|(b)))? +;;; and therefore we stop REGISTER removal once we see an ALTERNATION. + +(defgeneric remove-registers (regex) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Returns a deep copy of a REGEX (see COPY-REGEX) and +optionally removes embedded REGISTER objects if possible and if the +special variable REMOVE-REGISTERS-P is true.")) + +(defmethod remove-registers ((register register)) + (declare (special remove-registers-p reg-seen)) + (cond (remove-registers-p + (remove-registers (regex register))) + (t + ;; mark REG-SEEN as true so enclosing REPETITION objects + ;; (see method below) know if they contain a register or not + (setq reg-seen t) + (copy-regex register)))) + +(defmethod remove-registers ((repetition repetition)) + (let* (reg-seen + (inner-regex (remove-registers (regex repetition)))) + ;; REMOVE-REGISTERS will set REG-SEEN (see method above) if + ;; (REGEX REPETITION) contains a REGISTER + (declare (special reg-seen)) + (make-instance 'repetition + :regex inner-regex + :greedyp (greedyp repetition) + :minimum (minimum repetition) + :maximum (maximum repetition) + :min-len (min-len repetition) + :len (len repetition) + :contains-register-p reg-seen))) + +(defmethod remove-registers ((standalone standalone)) + (make-instance 'standalone + :regex (remove-registers (regex standalone)))) + +(defmethod remove-registers ((lookahead lookahead)) + (make-instance 'lookahead + :regex (remove-registers (regex lookahead)) + :positivep (positivep lookahead))) + +(defmethod remove-registers ((lookbehind lookbehind)) + (make-instance 'lookbehind + :regex (remove-registers (regex lookbehind)) + :positivep (positivep lookbehind) + :len (len lookbehind))) + +(defmethod remove-registers ((branch branch)) + (with-slots ((test test)) + branch + (make-instance 'branch + :test (if (typep test 'regex) + (remove-registers test) + test) + :then-regex (remove-registers (then-regex branch)) + :else-regex (remove-registers (else-regex branch))))) + +(defmethod remove-registers ((alternation alternation)) + (declare (special remove-registers-p)) + ;; an ALTERNATION, so we can't remove REGISTER objects further down + (setq remove-registers-p nil) + (copy-regex alternation)) + +(defmethod remove-registers ((regex regex)) + (copy-regex regex)) + +(defmethod remove-registers ((seq seq)) + (make-instance 'seq + :elements (mapcar #'remove-registers (elements seq)))) + +(defgeneric everythingp (regex) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Returns an EVERYTHING object if REGEX is equivalent +to this object, otherwise NIL. So, \"(.){1}\" would return true +(i.e. the object corresponding to \".\", for example.")) + +(defmethod everythingp ((seq seq)) + ;; we might have degenerate cases like (:SEQUENCE :VOID ...) + ;; due to the parsing process + (let ((cleaned-elements (remove-if #'(lambda (element) + (typep element 'void)) + (elements seq)))) + (and (= 1 (length cleaned-elements)) + (everythingp (first cleaned-elements))))) + +(defmethod everythingp ((alternation alternation)) + (with-slots ((choices choices)) + alternation + (and (= 1 (length choices)) + ;; this is unlikely to happen for human-generated regexes, + ;; but machine-generated ones might look like this + (everythingp (first choices))))) + +(defmethod everythingp ((repetition repetition)) + (with-slots ((maximum maximum) + (minimum minimum) + (regex regex)) + repetition + (and maximum + (= 1 minimum maximum) + ;; treat "{1,1}" like "" + (everythingp regex)))) + +(defmethod everythingp ((register register)) + (everythingp (regex register))) + +(defmethod everythingp ((standalone standalone)) + (everythingp (regex standalone))) + +(defmethod everythingp ((everything everything)) + everything) + +(defmethod everythingp ((regex regex)) + ;; the general case for ANCHOR, BACK-REFERENCE, BRANCH, CHAR-CLASS, + ;; LOOKAHEAD, LOOKBEHIND, STR, VOID, FILTER, and WORD-BOUNDARY + nil) + +(defgeneric regex-length (regex) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Return the length of REGEX if it is fixed, NIL otherwise.")) + +(defmethod regex-length ((seq seq)) + ;; simply add all inner lengths unless one of them is NIL + (loop for sub-regex in (elements seq) + for len = (regex-length sub-regex) + if (not len) do (return nil) + sum len)) + +(defmethod regex-length ((alternation alternation)) + ;; only return a true value if all inner lengths are non-NIL and + ;; mutually equal + (loop for sub-regex in (choices alternation) + for old-len = nil then len + for len = (regex-length sub-regex) + if (or (not len) + (and old-len (/= len old-len))) do (return nil) + finally (return len))) + +(defmethod regex-length ((branch branch)) + ;; only return a true value if both alternations have a length and + ;; if they're equal + (let ((then-length (regex-length (then-regex branch)))) + (and then-length + (eql then-length (regex-length (else-regex branch))) + then-length))) + +(defmethod regex-length ((repetition repetition)) + ;; we can only compute the length of a REPETITION object if the + ;; number of repetitions is fixed; note that we don't call + ;; REGEX-LENGTH for the inner regex, we assume that the LEN slot is + ;; always set correctly + (with-slots ((len len) + (minimum minimum) + (maximum maximum)) + repetition + (if (and len + (eq minimum maximum)) + (* minimum len) + nil))) + +(defmethod regex-length ((register register)) + (regex-length (regex register))) + +(defmethod regex-length ((standalone standalone)) + (regex-length (regex standalone))) + +(defmethod regex-length ((back-reference back-reference)) + ;; with enough effort we could possibly do better here, but + ;; currently we just give up and return NIL + nil) + +(defmethod regex-length ((char-class char-class)) + 1) + +(defmethod regex-length ((everything everything)) + 1) + +(defmethod regex-length ((str str)) + (len str)) + +(defmethod regex-length ((filter filter)) + (len filter)) + +(defmethod regex-length ((regex regex)) + ;; the general case for ANCHOR, LOOKAHEAD, LOOKBEHIND, VOID, and + ;; WORD-BOUNDARY (which all have zero-length) + 0) + +(defgeneric regex-min-length (regex) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Returns the minimal length of REGEX.")) + +(defmethod regex-min-length ((seq seq)) + ;; simply add all inner minimal lengths + (loop for sub-regex in (elements seq) + for len = (regex-min-length sub-regex) + sum len)) + +(defmethod regex-min-length ((alternation alternation)) + ;; minimal length of an alternation is the minimal length of the + ;; "shortest" element + (loop for sub-regex in (choices alternation) + for len = (regex-min-length sub-regex) + minimize len)) + +(defmethod regex-min-length ((branch branch)) + ;; minimal length of both alternations + (min (regex-min-length (then-regex branch)) + (regex-min-length (else-regex branch)))) + +(defmethod regex-min-length ((repetition repetition)) + ;; obviously the product of the inner minimal length and the minimal + ;; number of repetitions + (* (minimum repetition) (min-len repetition))) + +(defmethod regex-min-length ((register register)) + (regex-min-length (regex register))) + +(defmethod regex-min-length ((standalone standalone)) + (regex-min-length (regex standalone))) + +(defmethod regex-min-length ((char-class char-class)) + 1) + +(defmethod regex-min-length ((everything everything)) + 1) + +(defmethod regex-min-length ((str str)) + (len str)) + +(defmethod regex-min-length ((filter filter)) + (or (len filter) + 0)) + +(defmethod regex-min-length ((regex regex)) + ;; the general case for ANCHOR, BACK-REFERENCE, LOOKAHEAD, + ;; LOOKBEHIND, VOID, and WORD-BOUNDARY + 0) + +(defgeneric compute-offsets (regex start-pos) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (:documentation "Returns the offset the following regex would have +relative to START-POS or NIL if we can't compute it. Sets the OFFSET +slot of REGEX to START-POS if REGEX is a STR. May also affect OFFSET +slots of STR objects further down the tree.")) + +;; note that we're actually only interested in the offset of +;; "top-level" STR objects (see ADVANCE-FN in the SCAN function) so we +;; can stop at variable-length alternations and don't need to descend +;; into repetitions + +(defmethod compute-offsets ((seq seq) start-pos) + (loop for element in (elements seq) + ;; advance offset argument for next call while looping through + ;; the elements + for pos = start-pos then curr-offset + for curr-offset = (compute-offsets element pos) + while curr-offset + finally (return curr-offset))) + +(defmethod compute-offsets ((alternation alternation) start-pos) + (loop for choice in (choices alternation) + for old-offset = nil then curr-offset + for curr-offset = (compute-offsets choice start-pos) + ;; we stop immediately if two alternations don't result in the + ;; same offset + if (or (not curr-offset) + (and old-offset (/= curr-offset old-offset))) + do (return nil) + finally (return curr-offset))) + +(defmethod compute-offsets ((branch branch) start-pos) + ;; only return offset if both alternations have equal value + (let ((then-offset (compute-offsets (then-regex branch) start-pos))) + (and then-offset + (eql then-offset (compute-offsets (else-regex branch) start-pos)) + then-offset))) + +(defmethod compute-offsets ((repetition repetition) start-pos) + ;; no need to descend into the inner regex + (with-slots ((len len) + (minimum minimum) + (maximum maximum)) + repetition + (if (and len + (eq minimum maximum)) + ;; fixed number of repetitions, so we know how to proceed + (+ start-pos (* minimum len)) + ;; otherwise return NIL + nil))) + +(defmethod compute-offsets ((register register) start-pos) + (compute-offsets (regex register) start-pos)) + +(defmethod compute-offsets ((standalone standalone) start-pos) + (compute-offsets (regex standalone) start-pos)) + +(defmethod compute-offsets ((char-class char-class) start-pos) + (1+ start-pos)) + +(defmethod compute-offsets ((everything everything) start-pos) + (1+ start-pos)) + +(defmethod compute-offsets ((str str) start-pos) + (setf (offset str) start-pos) + (+ start-pos (len str))) + +(defmethod compute-offsets ((back-reference back-reference) start-pos) + ;; with enough effort we could possibly do better here, but + ;; currently we just give up and return NIL + (declare (ignore start-pos)) + nil) + +(defmethod compute-offsets ((filter filter) start-pos) + (let ((len (len filter))) + (if len + (+ start-pos len) + nil))) + +(defmethod compute-offsets ((regex regex) start-pos) + ;; the general case for ANCHOR, LOOKAHEAD, LOOKBEHIND, VOID, and + ;; WORD-BOUNDARY (which all have zero-length) + start-pos) diff --git a/practicals/libraries/cl-ppcre-1.2.3/repetition-closures.lisp b/practicals/libraries/cl-ppcre-1.2.3/repetition-closures.lisp new file mode 100644 index 0000000..f0a8667 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/repetition-closures.lisp @@ -0,0 +1,868 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/repetition-closures.lisp,v 1.20 2004/04/20 11:37:36 edi Exp $ + +;;; This is actually a part of closures.lisp which we put into a +;;; separate file because it is rather complex. We only deal with +;;; REPETITIONs here. Note that this part of the code contains some +;;; rather crazy micro-optimizations which were introduced to be as +;;; competitive with Perl as possible in tight loops. + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre) + +(defmacro incf-after (place &optional (delta 1) &environment env) + "Utility macro inspired by C's \"place++\", i.e. first return the +value of PLACE and afterwards increment it by DELTA." + (with-unique-names (%temp) + (multiple-value-bind (vars vals store-vars writer-form reader-form) + (get-setf-expansion place env) + `(let* (,@(mapcar #'list vars vals) + (,%temp ,reader-form) + (,(car store-vars) (+ ,%temp ,delta))) + ,writer-form + ,%temp)))) + +;; code for greedy repetitions with minimum zero + +(defmacro greedy-constant-length-closure (check-curr-pos) + "This is the template for simple greedy repetitions (where simple +means that the minimum number of repetitions is zero, that the inner +regex to be checked is of fixed length LEN, and that it doesn't +contain registers, i.e. there's no need for backtracking). +CHECK-CURR-POS is a form which checks whether the inner regex of the +repetition matches at CURR-POS." + `(if maximum + (lambda (start-pos) + (declare (type fixnum start-pos maximum)) + ;; because we know LEN we know in advance where to stop at the + ;; latest; we also take into consideration MIN-REST, i.e. the + ;; minimal length of the part behind the repetition + (let ((target-end-pos (min (1+ (- *end-pos* len min-rest)) + ;; don't go further than MAXIMUM + ;; repetitions, of course + (+ start-pos + (the fixnum (* len maximum))))) + (curr-pos start-pos)) + (declare (type fixnum target-end-pos curr-pos)) + (block greedy-constant-length-matcher + ;; we use an ugly TAGBODY construct because this might be a + ;; tight loop and this version is a bit faster than our LOOP + ;; version (at least in CMUCL) + (tagbody + forward-loop + ;; first go forward as far as possible, i.e. while + ;; the inner regex matches + (when (>= curr-pos target-end-pos) + (go backward-loop)) + (when ,check-curr-pos + (incf curr-pos len) + (go forward-loop)) + backward-loop + ;; now go back LEN steps each until we're able to match + ;; the rest of the regex + (when (< curr-pos start-pos) + (return-from greedy-constant-length-matcher nil)) + (let ((result (funcall next-fn curr-pos))) + (when result + (return-from greedy-constant-length-matcher result))) + (decf curr-pos len) + (go backward-loop))))) + ;; basically the same code; it's just a bit easier because we're + ;; not bounded by MAXIMUM + (lambda (start-pos) + (declare (type fixnum start-pos)) + (let ((target-end-pos (1+ (- *end-pos* len min-rest))) + (curr-pos start-pos)) + (declare (type fixnum target-end-pos curr-pos)) + (block greedy-constant-length-matcher + (tagbody + forward-loop + (when (>= curr-pos target-end-pos) + (go backward-loop)) + (when ,check-curr-pos + (incf curr-pos len) + (go forward-loop)) + backward-loop + (when (< curr-pos start-pos) + (return-from greedy-constant-length-matcher nil)) + (let ((result (funcall next-fn curr-pos))) + (when result + (return-from greedy-constant-length-matcher result))) + (decf curr-pos len) + (go backward-loop))))))) + +(defun create-greedy-everything-matcher (maximum min-rest next-fn) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (type fixnum min-rest) + (type function next-fn)) + "Creates a closure which just matches as far ahead as possible, +i.e. a closure for a dot in single-line mode." + (if maximum + (lambda (start-pos) + (declare (type fixnum start-pos maximum)) + ;; because we know LEN we know in advance where to stop at the + ;; latest; we also take into consideration MIN-REST, i.e. the + ;; minimal length of the part behind the repetition + (let ((target-end-pos (min (+ start-pos maximum) + (- *end-pos* min-rest)))) + (declare (type fixnum target-end-pos)) + ;; start from the highest possible position and go backward + ;; until we're able to match the rest of the regex + (loop for curr-pos of-type fixnum from target-end-pos downto start-pos + thereis (funcall next-fn curr-pos)))) + ;; basically the same code; it's just a bit easier because we're + ;; not bounded by MAXIMUM + (lambda (start-pos) + (declare (type fixnum start-pos)) + (let ((target-end-pos (- *end-pos* min-rest))) + (declare (type fixnum target-end-pos)) + (loop for curr-pos of-type fixnum from target-end-pos downto start-pos + thereis (funcall next-fn curr-pos)))))) + +(defmethod create-greedy-constant-length-matcher ((repetition repetition) + next-fn) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Creates a closure which tries to match REPETITION. It is assumed +that REPETITION is greedy and the minimal number of repetitions is +zero. It is furthermore assumed that the inner regex of REPETITION is +of fixed length and doesn't contain registers." + (let ((len (len repetition)) + (maximum (maximum repetition)) + (regex (regex repetition)) + (min-rest (min-rest repetition))) + (declare (type fixnum len min-rest) + (type function next-fn)) + (cond ((zerop len) + ;; inner regex has zero-length, so we can discard it + ;; completely + next-fn) + (t + ;; now first try to optimize for a couple of common cases + (typecase regex + (str + (let ((str (str regex))) + (if (= 1 len) + ;; a single character + (let ((chr (schar str 0))) + (if (case-insensitive-p regex) + (greedy-constant-length-closure + (char-equal chr (schar *string* curr-pos))) + (greedy-constant-length-closure + (char= chr (schar *string* curr-pos))))) + ;; a string + (if (case-insensitive-p regex) + (greedy-constant-length-closure + (*string*-equal str curr-pos (+ curr-pos len) 0 len)) + (greedy-constant-length-closure + (*string*= str curr-pos (+ curr-pos len) 0 len)))))) + (char-class + ;; a character class + (insert-char-class-tester (regex (schar *string* curr-pos)) + (if (invertedp regex) + (greedy-constant-length-closure + (not (char-class-test))) + (greedy-constant-length-closure + (char-class-test))))) + (everything + ;; an EVERYTHING object, i.e. a dot + (if (single-line-p regex) + (create-greedy-everything-matcher maximum min-rest next-fn) + (greedy-constant-length-closure + (char/= #\Newline (schar *string* curr-pos))))) + (t + ;; the general case - we build an inner matcher which + ;; just checks for immediate success, i.e. NEXT-FN is + ;; #'IDENTITY + (let ((inner-matcher (create-matcher-aux regex #'identity))) + (declare (type function inner-matcher)) + (greedy-constant-length-closure + (funcall inner-matcher curr-pos))))))))) + +(defmethod create-greedy-no-zero-matcher ((repetition repetition) next-fn) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Creates a closure which tries to match REPETITION. It is assumed +that REPETITION is greedy and the minimal number of repetitions is +zero. It is furthermore assumed that the inner regex of REPETITION can +never match a zero-length string (or instead the maximal number of +repetitions is 1)." + (let ((maximum (maximum repetition)) + ;; REPEAT-MATCHER is part of the closure's environment but it + ;; can only be defined after GREEDY-AUX is defined + repeat-matcher) + (declare (type function next-fn)) + (cond + ((eql maximum 1) + ;; this is essentially like the next case but with a known + ;; MAXIMUM of 1 we can get away without a counter; note that + ;; we always arrive here if CONVERT optimizes * to + ;; (?:*)? + (setq repeat-matcher + (create-matcher-aux (regex repetition) next-fn)) + (lambda (start-pos) + (declare (type function repeat-matcher)) + (or (funcall repeat-matcher start-pos) + (funcall next-fn start-pos)))) + (maximum + ;; we make a reservation for our slot in *REPEAT-COUNTERS* + ;; because we need to keep track whether we've reached MAXIMUM + ;; repetitions + (let ((rep-num (incf-after *rep-num*))) + (flet ((greedy-aux (start-pos) + (declare (type fixnum start-pos maximum rep-num) + (type function repeat-matcher)) + ;; the actual matcher which first tries to match the + ;; inner regex of REPETITION (if we haven't done so + ;; too often) and on failure calls NEXT-FN + (or (and (< (aref *repeat-counters* rep-num) maximum) + (incf (aref *repeat-counters* rep-num)) + ;; note that REPEAT-MATCHER will call + ;; GREEDY-AUX again recursively + (prog1 + (funcall repeat-matcher start-pos) + (decf (aref *repeat-counters* rep-num)))) + (funcall next-fn start-pos)))) + ;; create a closure to match the inner regex and to + ;; implement backtracking via GREEDY-AUX + (setq repeat-matcher + (create-matcher-aux (regex repetition) #'greedy-aux)) + ;; the closure we return is just a thin wrapper around + ;; GREEDY-AUX to initialize the repetition counter + (lambda (start-pos) + (declare (type fixnum start-pos)) + (setf (aref *repeat-counters* rep-num) 0) + (greedy-aux start-pos))))) + (t + ;; easier code because we're not bounded by MAXIMUM, but + ;; basically the same + (flet ((greedy-aux (start-pos) + (declare (type fixnum start-pos) + (type function repeat-matcher)) + (or (funcall repeat-matcher start-pos) + (funcall next-fn start-pos)))) + (setq repeat-matcher + (create-matcher-aux (regex repetition) #'greedy-aux)) + #'greedy-aux))))) + +(defmethod create-greedy-matcher ((repetition repetition) next-fn) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Creates a closure which tries to match REPETITION. It is assumed +that REPETITION is greedy and the minimal number of repetitions is +zero." + (let ((maximum (maximum repetition)) + ;; we make a reservation for our slot in *LAST-POS-STORES* because + ;; we have to watch out for endless loops as the inner regex might + ;; match zero-length strings + (zero-length-num (incf-after *zero-length-num*)) + ;; REPEAT-MATCHER is part of the closure's environment but it + ;; can only be defined after GREEDY-AUX is defined + repeat-matcher) + (declare (type fixnum zero-length-num) + (type function next-fn)) + (cond + (maximum + ;; we make a reservation for our slot in *REPEAT-COUNTERS* + ;; because we need to keep track whether we've reached MAXIMUM + ;; repetitions + (let ((rep-num (incf-after *rep-num*))) + (flet ((greedy-aux (start-pos) + ;; the actual matcher which first tries to match the + ;; inner regex of REPETITION (if we haven't done so + ;; too often) and on failure calls NEXT-FN + (declare (type fixnum start-pos maximum rep-num) + (type function repeat-matcher)) + (let ((old-last-pos + (svref *last-pos-stores* zero-length-num))) + (when (and old-last-pos + (= (the fixnum old-last-pos) start-pos)) + ;; stop immediately if we've been here before, + ;; i.e. if the last attempt matched a zero-length + ;; string + (return-from greedy-aux (funcall next-fn start-pos))) + ;; otherwise remember this position for the next + ;; repetition + (setf (svref *last-pos-stores* zero-length-num) start-pos) + (or (and (< (aref *repeat-counters* rep-num) maximum) + (incf (aref *repeat-counters* rep-num)) + ;; note that REPEAT-MATCHER will call + ;; GREEDY-AUX again recursively + (prog1 + (funcall repeat-matcher start-pos) + (decf (aref *repeat-counters* rep-num)) + (setf (svref *last-pos-stores* zero-length-num) + old-last-pos))) + (funcall next-fn start-pos))))) + ;; create a closure to match the inner regex and to + ;; implement backtracking via GREEDY-AUX + (setq repeat-matcher + (create-matcher-aux (regex repetition) #'greedy-aux)) + ;; the closure we return is just a thin wrapper around + ;; GREEDY-AUX to initialize the repetition counter and our + ;; slot in *LAST-POS-STORES* + (lambda (start-pos) + (declare (type fixnum start-pos)) + (setf (aref *repeat-counters* rep-num) 0 + (svref *last-pos-stores* zero-length-num) nil) + (greedy-aux start-pos))))) + (t + ;; easier code because we're not bounded by MAXIMUM, but + ;; basically the same + (flet ((greedy-aux (start-pos) + (declare (type fixnum start-pos) + (type function repeat-matcher)) + (let ((old-last-pos + (svref *last-pos-stores* zero-length-num))) + (when (and old-last-pos + (= (the fixnum old-last-pos) start-pos)) + (return-from greedy-aux (funcall next-fn start-pos))) + (setf (svref *last-pos-stores* zero-length-num) start-pos) + (or (prog1 + (funcall repeat-matcher start-pos) + (setf (svref *last-pos-stores* zero-length-num) old-last-pos)) + (funcall next-fn start-pos))))) + (setq repeat-matcher + (create-matcher-aux (regex repetition) #'greedy-aux)) + (lambda (start-pos) + (declare (type fixnum start-pos)) + (setf (svref *last-pos-stores* zero-length-num) nil) + (greedy-aux start-pos))))))) + +;; code for non-greedy repetitions with minimum zero + +(defmacro non-greedy-constant-length-closure (check-curr-pos) + "This is the template for simple non-greedy repetitions (where +simple means that the minimum number of repetitions is zero, that the +inner regex to be checked is of fixed length LEN, and that it doesn't +contain registers, i.e. there's no need for backtracking). +CHECK-CURR-POS is a form which checks whether the inner regex of the +repetition matches at CURR-POS." + `(if maximum + (lambda (start-pos) + (declare (type fixnum start-pos maximum)) + ;; because we know LEN we know in advance where to stop at the + ;; latest; we also take into consideration MIN-REST, i.e. the + ;; minimal length of the part behind the repetition + (let ((target-end-pos (min (1+ (- *end-pos* len min-rest)) + (+ start-pos + (the fixnum (* len maximum)))))) + ;; move forward by LEN and always try NEXT-FN first, then + ;; CHECK-CUR-POS + (loop for curr-pos of-type fixnum from start-pos + below target-end-pos + by len + thereis (funcall next-fn curr-pos) + while ,check-curr-pos + finally (return (funcall next-fn curr-pos))))) + ;; basically the same code; it's just a bit easier because we're + ;; not bounded by MAXIMUM + (lambda (start-pos) + (declare (type fixnum start-pos)) + (let ((target-end-pos (1+ (- *end-pos* len min-rest)))) + (loop for curr-pos of-type fixnum from start-pos + below target-end-pos + by len + thereis (funcall next-fn curr-pos) + while ,check-curr-pos + finally (return (funcall next-fn curr-pos))))))) + +(defmethod create-non-greedy-constant-length-matcher ((repetition repetition) next-fn) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Creates a closure which tries to match REPETITION. It is assumed +that REPETITION is non-greedy and the minimal number of repetitions is +zero. It is furthermore assumed that the inner regex of REPETITION is +of fixed length and doesn't contain registers." + (let ((len (len repetition)) + (maximum (maximum repetition)) + (regex (regex repetition)) + (min-rest (min-rest repetition))) + (declare (type fixnum len min-rest) + (type function next-fn)) + (cond ((zerop len) + ;; inner regex has zero-length, so we can discard it + ;; completely + next-fn) + (t + ;; now first try to optimize for a couple of common cases + (typecase regex + (str + (let ((str (str regex))) + (if (= 1 len) + ;; a single character + (let ((chr (schar str 0))) + (if (case-insensitive-p regex) + (non-greedy-constant-length-closure + (char-equal chr (schar *string* curr-pos))) + (non-greedy-constant-length-closure + (char= chr (schar *string* curr-pos))))) + ;; a string + (if (case-insensitive-p regex) + (non-greedy-constant-length-closure + (*string*-equal str curr-pos (+ curr-pos len) 0 len)) + (non-greedy-constant-length-closure + (*string*= str curr-pos (+ curr-pos len) 0 len)))))) + (char-class + ;; a character class + (insert-char-class-tester (regex (schar *string* curr-pos)) + (if (invertedp regex) + (non-greedy-constant-length-closure + (not (char-class-test))) + (non-greedy-constant-length-closure + (char-class-test))))) + (everything + (if (single-line-p regex) + ;; a dot which really can match everything; we rely + ;; on the compiler to optimize this away + (non-greedy-constant-length-closure + t) + ;; a dot which has to watch out for #\Newline + (non-greedy-constant-length-closure + (char/= #\Newline (schar *string* curr-pos))))) + (t + ;; the general case - we build an inner matcher which + ;; just checks for immediate success, i.e. NEXT-FN is + ;; #'IDENTITY + (let ((inner-matcher (create-matcher-aux regex #'identity))) + (declare (type function inner-matcher)) + (non-greedy-constant-length-closure + (funcall inner-matcher curr-pos))))))))) + +(defmethod create-non-greedy-no-zero-matcher ((repetition repetition) next-fn) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Creates a closure which tries to match REPETITION. It is assumed +that REPETITION is non-greedy and the minimal number of repetitions is +zero. It is furthermore assumed that the inner regex of REPETITION can +never match a zero-length string (or instead the maximal number of +repetitions is 1)." + (let ((maximum (maximum repetition)) + ;; REPEAT-MATCHER is part of the closure's environment but it + ;; can only be defined after NON-GREEDY-AUX is defined + repeat-matcher) + (declare (type function next-fn)) + (cond + ((eql maximum 1) + ;; this is essentially like the next case but with a known + ;; MAXIMUM of 1 we can get away without a counter + (setq repeat-matcher + (create-matcher-aux (regex repetition) next-fn)) + (lambda (start-pos) + (declare (type function repeat-matcher)) + (or (funcall next-fn start-pos) + (funcall repeat-matcher start-pos)))) + (maximum + ;; we make a reservation for our slot in *REPEAT-COUNTERS* + ;; because we need to keep track whether we've reached MAXIMUM + ;; repetitions + (let ((rep-num (incf-after *rep-num*))) + (flet ((non-greedy-aux (start-pos) + ;; the actual matcher which first calls NEXT-FN and + ;; on failure tries to match the inner regex of + ;; REPETITION (if we haven't done so too often) + (declare (type fixnum start-pos maximum rep-num) + (type function repeat-matcher)) + (or (funcall next-fn start-pos) + (and (< (aref *repeat-counters* rep-num) maximum) + (incf (aref *repeat-counters* rep-num)) + ;; note that REPEAT-MATCHER will call + ;; NON-GREEDY-AUX again recursively + (prog1 + (funcall repeat-matcher start-pos) + (decf (aref *repeat-counters* rep-num))))))) + ;; create a closure to match the inner regex and to + ;; implement backtracking via NON-GREEDY-AUX + (setq repeat-matcher + (create-matcher-aux (regex repetition) #'non-greedy-aux)) + ;; the closure we return is just a thin wrapper around + ;; NON-GREEDY-AUX to initialize the repetition counter + (lambda (start-pos) + (declare (type fixnum start-pos)) + (setf (aref *repeat-counters* rep-num) 0) + (non-greedy-aux start-pos))))) + (t + ;; easier code because we're not bounded by MAXIMUM, but + ;; basically the same + (flet ((non-greedy-aux (start-pos) + (declare (type fixnum start-pos) + (type function repeat-matcher)) + (or (funcall next-fn start-pos) + (funcall repeat-matcher start-pos)))) + (setq repeat-matcher + (create-matcher-aux (regex repetition) #'non-greedy-aux)) + #'non-greedy-aux))))) + +(defmethod create-non-greedy-matcher ((repetition repetition) next-fn) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Creates a closure which tries to match REPETITION. It is assumed +that REPETITION is non-greedy and the minimal number of repetitions is +zero." + ;; we make a reservation for our slot in *LAST-POS-STORES* because + ;; we have to watch out for endless loops as the inner regex might + ;; match zero-length strings + (let ((zero-length-num (incf-after *zero-length-num*)) + (maximum (maximum repetition)) + ;; REPEAT-MATCHER is part of the closure's environment but it + ;; can only be defined after NON-GREEDY-AUX is defined + repeat-matcher) + (declare (type fixnum zero-length-num) + (type function next-fn)) + (cond + (maximum + ;; we make a reservation for our slot in *REPEAT-COUNTERS* + ;; because we need to keep track whether we've reached MAXIMUM + ;; repetitions + (let ((rep-num (incf-after *rep-num*))) + (flet ((non-greedy-aux (start-pos) + ;; the actual matcher which first calls NEXT-FN and + ;; on failure tries to match the inner regex of + ;; REPETITION (if we haven't done so too often) + (declare (type fixnum start-pos maximum rep-num) + (type function repeat-matcher)) + (let ((old-last-pos + (svref *last-pos-stores* zero-length-num))) + (when (and old-last-pos + (= (the fixnum old-last-pos) start-pos)) + ;; stop immediately if we've been here before, + ;; i.e. if the last attempt matched a zero-length + ;; string + (return-from non-greedy-aux (funcall next-fn start-pos))) + ;; otherwise remember this position for the next + ;; repetition + (setf (svref *last-pos-stores* zero-length-num) start-pos) + (or (funcall next-fn start-pos) + (and (< (aref *repeat-counters* rep-num) maximum) + (incf (aref *repeat-counters* rep-num)) + ;; note that REPEAT-MATCHER will call + ;; NON-GREEDY-AUX again recursively + (prog1 + (funcall repeat-matcher start-pos) + (decf (aref *repeat-counters* rep-num)) + (setf (svref *last-pos-stores* zero-length-num) + old-last-pos))))))) + ;; create a closure to match the inner regex and to + ;; implement backtracking via NON-GREEDY-AUX + (setq repeat-matcher + (create-matcher-aux (regex repetition) #'non-greedy-aux)) + ;; the closure we return is just a thin wrapper around + ;; NON-GREEDY-AUX to initialize the repetition counter and our + ;; slot in *LAST-POS-STORES* + (lambda (start-pos) + (declare (type fixnum start-pos)) + (setf (aref *repeat-counters* rep-num) 0 + (svref *last-pos-stores* zero-length-num) nil) + (non-greedy-aux start-pos))))) + (t + ;; easier code because we're not bounded by MAXIMUM, but + ;; basically the same + (flet ((non-greedy-aux (start-pos) + (declare (type fixnum start-pos) + (type function repeat-matcher)) + (let ((old-last-pos + (svref *last-pos-stores* zero-length-num))) + (when (and old-last-pos + (= (the fixnum old-last-pos) start-pos)) + (return-from non-greedy-aux (funcall next-fn start-pos))) + (setf (svref *last-pos-stores* zero-length-num) start-pos) + (or (funcall next-fn start-pos) + (prog1 + (funcall repeat-matcher start-pos) + (setf (svref *last-pos-stores* zero-length-num) + old-last-pos)))))) + (setq repeat-matcher + (create-matcher-aux (regex repetition) #'non-greedy-aux)) + (lambda (start-pos) + (declare (type fixnum start-pos)) + (setf (svref *last-pos-stores* zero-length-num) nil) + (non-greedy-aux start-pos))))))) + +;; code for constant repetitions, i.e. those with a fixed number of repetitions + +(defmacro constant-repetition-constant-length-closure (check-curr-pos) + "This is the template for simple constant repetitions (where simple +means that the inner regex to be checked is of fixed length LEN, and +that it doesn't contain registers, i.e. there's no need for +backtracking) and where constant means that MINIMUM is equal to +MAXIMUM. CHECK-CURR-POS is a form which checks whether the inner regex +of the repetition matches at CURR-POS." + `(lambda (start-pos) + (declare (type fixnum start-pos)) + (let ((target-end-pos (+ start-pos + (the fixnum (* len repetitions))))) + (declare (type fixnum target-end-pos)) + ;; first check if we won't go beyond the end of the string + (and (>= *end-pos* target-end-pos) + ;; then loop through all repetitions step by step + (loop for curr-pos of-type fixnum from start-pos + below target-end-pos + by len + always ,check-curr-pos) + ;; finally call NEXT-FN if we made it that far + (funcall next-fn target-end-pos))))) + +(defmethod create-constant-repetition-constant-length-matcher + ((repetition repetition) next-fn) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Creates a closure which tries to match REPETITION. It is assumed +that REPETITION has a constant number of repetitions. It is +furthermore assumed that the inner regex of REPETITION is of fixed +length and doesn't contain registers." + (let ((len (len repetition)) + (repetitions (minimum repetition)) + (regex (regex repetition))) + (declare (type fixnum len repetitions) + (type function next-fn)) + (if (zerop len) + ;; if the length is zero it suffices to try once + (create-matcher-aux regex next-fn) + ;; otherwise try to optimize for a couple of common cases + (typecase regex + (str + (let ((str (str regex))) + (if (= 1 len) + ;; a single character + (let ((chr (schar str 0))) + (if (case-insensitive-p regex) + (constant-repetition-constant-length-closure + (and (char-equal chr (schar *string* curr-pos)) + (1+ curr-pos))) + (constant-repetition-constant-length-closure + (and (char= chr (schar *string* curr-pos)) + (1+ curr-pos))))) + ;; a string + (if (case-insensitive-p regex) + (constant-repetition-constant-length-closure + (let ((next-pos (+ curr-pos len))) + (declare (type fixnum next-pos)) + (and (*string*-equal str curr-pos next-pos 0 len) + next-pos))) + (constant-repetition-constant-length-closure + (let ((next-pos (+ curr-pos len))) + (declare (type fixnum next-pos)) + (and (*string*= str curr-pos next-pos 0 len) + next-pos))))))) + (char-class + ;; a character class + (insert-char-class-tester (regex (schar *string* curr-pos)) + (if (invertedp regex) + (constant-repetition-constant-length-closure + (and (not (char-class-test)) + (1+ curr-pos))) + (constant-repetition-constant-length-closure + (and (char-class-test) + (1+ curr-pos)))))) + (everything + (if (single-line-p regex) + ;; a dot which really matches everything - we just have to + ;; advance the index into *STRING* accordingly and check + ;; if we didn't go past the end + (lambda (start-pos) + (declare (type fixnum start-pos)) + (let ((next-pos (+ start-pos repetitions))) + (declare (type fixnum next-pos)) + (and (<= next-pos *end-pos*) + (funcall next-fn next-pos)))) + ;; a dot which is not in single-line-mode - make sure we + ;; don't match #\Newline + (constant-repetition-constant-length-closure + (and (char/= #\Newline (schar *string* curr-pos)) + (1+ curr-pos))))) + (t + ;; the general case - we build an inner matcher which just + ;; checks for immediate success, i.e. NEXT-FN is #'IDENTITY + (let ((inner-matcher (create-matcher-aux regex #'identity))) + (declare (type function inner-matcher)) + (constant-repetition-constant-length-closure + (funcall inner-matcher curr-pos)))))))) + +(defmethod create-constant-repetition-matcher ((repetition repetition) next-fn) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Creates a closure which tries to match REPETITION. It is assumed +that REPETITION has a constant number of repetitions." + (let ((repetitions (minimum repetition)) + ;; we make a reservation for our slot in *REPEAT-COUNTERS* + ;; because we need to keep track of the number of repetitions + (rep-num (incf-after *rep-num*)) + ;; REPEAT-MATCHER is part of the closure's environment but it + ;; can only be defined after NON-GREEDY-AUX is defined + repeat-matcher) + (declare (type fixnum repetitions rep-num) + (type function next-fn)) + (if (zerop (min-len repetition)) + ;; we make a reservation for our slot in *LAST-POS-STORES* + ;; because we have to watch out for needless loops as the inner + ;; regex might match zero-length strings + (let ((zero-length-num (incf-after *zero-length-num*))) + (declare (type fixnum zero-length-num)) + (flet ((constant-aux (start-pos) + ;; the actual matcher which first calls NEXT-FN and + ;; on failure tries to match the inner regex of + ;; REPETITION (if we haven't done so too often) + (declare (type fixnum start-pos) + (type function repeat-matcher)) + (let ((old-last-pos + (svref *last-pos-stores* zero-length-num))) + (when (and old-last-pos + (= (the fixnum old-last-pos) start-pos)) + ;; if we've been here before we matched a + ;; zero-length string the last time, so we can + ;; just carry on because we will definitely be + ;; able to do this again often enough + (return-from constant-aux (funcall next-fn start-pos))) + ;; otherwise remember this position for the next + ;; repetition + (setf (svref *last-pos-stores* zero-length-num) start-pos) + (cond ((< (aref *repeat-counters* rep-num) repetitions) + ;; not enough repetitions yet, try it again + (incf (aref *repeat-counters* rep-num)) + ;; note that REPEAT-MATCHER will call + ;; CONSTANT-AUX again recursively + (prog1 + (funcall repeat-matcher start-pos) + (decf (aref *repeat-counters* rep-num)) + (setf (svref *last-pos-stores* zero-length-num) + old-last-pos))) + (t + ;; we're done - call NEXT-FN + (funcall next-fn start-pos)))))) + ;; create a closure to match the inner regex and to + ;; implement backtracking via CONSTANT-AUX + (setq repeat-matcher + (create-matcher-aux (regex repetition) #'constant-aux)) + ;; the closure we return is just a thin wrapper around + ;; CONSTANT-AUX to initialize the repetition counter + (lambda (start-pos) + (declare (type fixnum start-pos)) + (setf (aref *repeat-counters* rep-num) 0 + (aref *last-pos-stores* zero-length-num) nil) + (constant-aux start-pos)))) + ;; easier code because we don't have to care about zero-length + ;; matches but basically the same + (flet ((constant-aux (start-pos) + (declare (type fixnum start-pos) + (type function repeat-matcher)) + (cond ((< (aref *repeat-counters* rep-num) repetitions) + (incf (aref *repeat-counters* rep-num)) + (prog1 + (funcall repeat-matcher start-pos) + (decf (aref *repeat-counters* rep-num)))) + (t (funcall next-fn start-pos))))) + (setq repeat-matcher + (create-matcher-aux (regex repetition) #'constant-aux)) + (lambda (start-pos) + (declare (type fixnum start-pos)) + (setf (aref *repeat-counters* rep-num) 0) + (constant-aux start-pos)))))) + +;; the actual CREATE-MATCHER-AUX method for REPETITION objects which +;; utilizes all the functions and macros defined above + +(defmethod create-matcher-aux ((repetition repetition) next-fn) + (with-slots ((minimum minimum) + (maximum maximum) + (len len) + (min-len min-len) + (greedyp greedyp) + (contains-register-p contains-register-p)) + repetition + (cond ((and maximum + (zerop maximum)) + ;; this should have been optimized away by CONVERT but just + ;; in case... + (error "Got REPETITION with MAXIMUM 0 \(should not happen)")) + ((and maximum + (= minimum maximum 1)) + ;; this should have been optimized away by CONVERT but just + ;; in case... + (error "Got REPETITION with MAXIMUM 1 and MINIMUM 1 \(should not happen)")) + ((and (eql minimum maximum) + len + (not contains-register-p)) + (create-constant-repetition-constant-length-matcher repetition next-fn)) + ((eql minimum maximum) + (create-constant-repetition-matcher repetition next-fn)) + ((and greedyp + len + (not contains-register-p)) + (create-greedy-constant-length-matcher repetition next-fn)) + ((and greedyp + (or (plusp min-len) + (eql maximum 1))) + (create-greedy-no-zero-matcher repetition next-fn)) + (greedyp + (create-greedy-matcher repetition next-fn)) + ((and len + (plusp len) + (not contains-register-p)) + (create-non-greedy-constant-length-matcher repetition next-fn)) + ((or (plusp min-len) + (eql maximum 1)) + (create-non-greedy-no-zero-matcher repetition next-fn)) + (t + (create-non-greedy-matcher repetition next-fn))))) diff --git a/practicals/libraries/cl-ppcre-1.2.3/scanner.lisp b/practicals/libraries/cl-ppcre-1.2.3/scanner.lisp new file mode 100644 index 0000000..9df5d21 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/scanner.lisp @@ -0,0 +1,526 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/scanner.lisp,v 1.22 2004/12/09 09:23:37 edi Exp $ + +;;; Here the scanner for the actual regex as well as utility scanners +;;; for the constant start and end strings are created. + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre) + +(defmacro bmh-matcher-aux (&key case-insensitive-p) + "Auxiliary macro used by CREATE-BMH-MATCHER." + (let ((char-compare (if case-insensitive-p 'char-equal 'char=))) + `(lambda (start-pos) + (declare (type fixnum start-pos)) + (if (or (minusp start-pos) + (> (the fixnum (+ start-pos m)) *end-pos*)) + nil + (loop named bmh-matcher + for k of-type fixnum = (+ start-pos m -1) + then (+ k (max 1 (aref skip (char-code (schar *string* k))))) + while (< k *end-pos*) + do (loop for j of-type fixnum downfrom (1- m) + for i of-type fixnum downfrom k + while (and (>= j 0) + (,char-compare (schar *string* i) + (schar pattern j))) + finally (if (minusp j) + (return-from bmh-matcher (1+ i))))))))) + +(defun create-bmh-matcher (pattern case-insensitive-p) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Returns a Boyer-Moore-Horspool matcher which searches the (special) +simple-string *STRING* for the first occurence of the substring +PATTERN. The search starts at the position START-POS within *STRING* +and stops before *END-POS* is reached. Depending on the second +argument the search is case-insensitive or not. If the special +variable *USE-BMH-MATCHERS* is NIL, use the standard SEARCH function +instead. (BMH matchers are faster but need much more space.)" + ;; see for + ;; details + (unless *use-bmh-matchers* + (let ((test (if case-insensitive-p #'char-equal #'char=))) + (return-from create-bmh-matcher + (lambda (start-pos) + (declare (type fixnum start-pos)) + (and (not (minusp start-pos)) + (search pattern + *string* + :start2 start-pos + :end2 *end-pos* + :test test)))))) + (let* ((m (length pattern)) + (skip (make-array *regex-char-code-limit* + :element-type 'fixnum + :initial-element m))) + (declare (type fixnum m)) + (loop for k of-type fixnum below m + if case-insensitive-p + do (setf (aref skip (char-code (char-upcase (schar pattern k)))) (- m k 1) + (aref skip (char-code (char-downcase (schar pattern k)))) (- m k 1)) + else + do (setf (aref skip (char-code (schar pattern k))) (- m k 1))) + (if case-insensitive-p + (bmh-matcher-aux :case-insensitive-p t) + (bmh-matcher-aux)))) + +(defmacro char-searcher-aux (&key case-insensitive-p) + "Auxiliary macro used by CREATE-CHAR-SEARCHER." + (let ((char-compare (if case-insensitive-p 'char-equal 'char=))) + `(lambda (start-pos) + (declare (type fixnum start-pos)) + (loop for i of-type fixnum from start-pos below *end-pos* + thereis (and (,char-compare (schar *string* i) chr) i))))) + +(defun create-char-searcher (chr case-insensitive-p) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Returns a function which searches the (special) simple-string +*STRING* for the first occurence of the character CHR. The search +starts at the position START-POS within *STRING* and stops before +*END-POS* is reached. Depending on the second argument the search is +case-insensitive or not." + (if case-insensitive-p + (char-searcher-aux :case-insensitive-p t) + (char-searcher-aux))) + +(declaim (inline newline-skipper)) + +(defun newline-skipper (start-pos) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (type fixnum start-pos)) + "Find the next occurence of a character in *STRING* which is behind +a #\Newline." + ;; we can start with (1- START-POS) without testing for (PLUSP + ;; START-POS) because we know we'll never call NEWLINE-SKIPPER on + ;; the first iteration + (loop for i of-type fixnum from (1- start-pos) below *end-pos* + thereis (and (char= (schar *string* i) + #\Newline) + (1+ i)))) + +(defmacro insert-advance-fn (advance-fn) + "Creates the actual closure returned by CREATE-SCANNER-AUX by +replacing '(ADVANCE-FN-DEFINITION) with a suitable definition for +ADVANCE-FN. This is a utility macro used by CREATE-SCANNER-AUX." + (subst + advance-fn '(advance-fn-definition) + '(lambda (string start end) + (block scan + ;; initialize a couple of special variables used by the + ;; matchers (see file specials.lisp) + (let* ((*string* string) + (*start-pos* start) + (*end-pos* end) + ;; we will search forward for END-STRING if this value + ;; isn't at least as big as POS (see ADVANCE-FN), so it + ;; is safe to start to the left of *START-POS*; note + ;; that this value will _never_ be decremented - this + ;; is crucial to the scanning process + (*end-string-pos* (1- *start-pos*)) + ;; the next five will shadow the variables defined by + ;; DEFPARAMETER; at this point, we don't know if we'll + ;; actually use them, though + (*repeat-counters* *repeat-counters*) + (*last-pos-stores* *last-pos-stores*) + (*reg-starts* *reg-starts*) + (*regs-maybe-start* *regs-maybe-start*) + (*reg-ends* *reg-ends*) + ;; we might be able to optimize the scanning process by + ;; (virtually) shifting *START-POS* to the right + (scan-start-pos *start-pos*) + (starts-with-str (if start-string-test + (str starts-with) + nil)) + ;; we don't need to try further than MAX-END-POS + (max-end-pos (- *end-pos* min-len))) + (declare (type fixnum scan-start-pos) + (type function match-fn)) + ;; definition of ADVANCE-FN will be inserted here by macrology + (labels ((advance-fn-definition)) + (declare (inline advance-fn)) + (when (plusp rep-num) + ;; we have at least one REPETITION which needs to count + ;; the number of repetitions + (setq *repeat-counters* (make-array rep-num + :initial-element 0 + :element-type 'fixnum))) + (when (plusp zero-length-num) + ;; we have at least one REPETITION which needs to watch + ;; out for zero-length repetitions + (setq *last-pos-stores* (make-array zero-length-num + :initial-element nil))) + (when (plusp reg-num) + ;; we have registers in our regular expression + (setq *reg-starts* (make-array reg-num :initial-element nil) + *regs-maybe-start* (make-array reg-num :initial-element nil) + *reg-ends* (make-array reg-num :initial-element nil))) + (when end-anchored-p + ;; the regular expression has a constant end string which + ;; is anchored at the very end of the target string + ;; (perhaps modulo a #\Newline) + (let ((end-test-pos (- *end-pos* (the fixnum end-string-len)))) + (declare (type fixnum end-test-pos) + (type function end-string-test)) + (unless (setq *end-string-pos* (funcall end-string-test + end-test-pos)) + (when (and (= 1 (the fixnum end-anchored-p)) + (> *end-pos* scan-start-pos) + (char= #\Newline (schar *string* (1- *end-pos*)))) + ;; if we didn't find an end string candidate from + ;; END-TEST-POS and if a #\Newline at the end is + ;; allowed we try it again from one position to the + ;; left + (setq *end-string-pos* (funcall end-string-test + (1- end-test-pos)))))) + (unless (and *end-string-pos* + (<= *start-pos* *end-string-pos*)) + ;; no end string candidate found, so give up + (return-from scan nil)) + (when end-string-offset + ;; if the offset of the constant end string from the + ;; left of the regular expression is known we can start + ;; scanning further to the right; this is similar to + ;; what we might do in ADVANCE-FN + (setq scan-start-pos (max scan-start-pos + (- (the fixnum *end-string-pos*) + (the fixnum end-string-offset)))))) + (cond + (start-anchored-p + ;; we're anchored at the start of the target string, + ;; so no need to try again after first failure + (when (or (/= *start-pos* scan-start-pos) + (< max-end-pos *start-pos*)) + ;; if END-STRING-OFFSET has proven that we don't + ;; need to bother to scan from *START-POS* or if the + ;; minimal length of the regular expression is + ;; longer than the target string we give up + (return-from scan nil)) + (when starts-with-str + (locally + (declare (type fixnum starts-with-len)) + (cond ((and (case-insensitive-p starts-with) + (not (*string*-equal starts-with-str + *start-pos* + (+ *start-pos* + starts-with-len) + 0 starts-with-len))) + ;; the regular expression has a + ;; case-insensitive constant start string + ;; and we didn't find it + (return-from scan nil)) + ((and (not (case-insensitive-p starts-with)) + (not (*string*= starts-with-str + *start-pos* + (+ *start-pos* starts-with-len) + 0 starts-with-len))) + ;; the regular expression has a + ;; case-sensitive constant start string + ;; and we didn't find it + (return-from scan nil)) + (t nil)))) + (when (and end-string-test + (not end-anchored-p)) + ;; the regular expression has a constant end string + ;; which isn't anchored so we didn't check for it + ;; already + (block end-string-loop + ;; we temporarily use *END-STRING-POS* as our + ;; starting position to look for end string + ;; candidates + (setq *end-string-pos* *start-pos*) + (loop + (unless (setq *end-string-pos* + (funcall (the function end-string-test) + *end-string-pos*)) + ;; no end string candidate found, so give up + (return-from scan nil)) + (unless end-string-offset + ;; end string doesn't have an offset so we + ;; can start scanning now + (return-from end-string-loop)) + (let ((maybe-start-pos (- (the fixnum *end-string-pos*) + (the fixnum end-string-offset)))) + (cond ((= maybe-start-pos *start-pos*) + ;; offset of end string into regular + ;; expression matches start anchor - + ;; fine... + (return-from end-string-loop)) + ((and (< maybe-start-pos *start-pos*) + (< (+ *end-string-pos* end-string-len) *end-pos*)) + ;; no match but maybe we find another + ;; one to the right - try again + (incf *end-string-pos*)) + (t + ;; otherwise give up + (return-from scan nil))))))) + ;; if we got here we scan exactly once + (let ((next-pos (funcall match-fn *start-pos*))) + (when next-pos + (values (if next-pos *start-pos* nil) + next-pos + *reg-starts* + *reg-ends*)))) + (t + (loop for pos = (if starts-with-everything + ;; don't jump to the next + ;; #\Newline on the first + ;; iteration + scan-start-pos + (advance-fn scan-start-pos)) + then (advance-fn pos) + ;; give up if the regular expression can't fit + ;; into the rest of the target string + while (and pos + (<= (the fixnum pos) max-end-pos)) + do (let ((next-pos (funcall match-fn pos))) + (when next-pos + (return-from scan (values pos + next-pos + *reg-starts* + *reg-ends*))) + ;; not yet found, increment POS + #-cormanlisp (incf (the fixnum pos)) + #+cormanlisp (incf pos))))))))) + :test #'equalp)) + +(defun create-scanner-aux (match-fn + min-len + start-anchored-p + starts-with + start-string-test + end-anchored-p + end-string-test + end-string-len + end-string-offset + rep-num + zero-length-num + reg-num) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + (declare (type fixnum min-len zero-length-num rep-num reg-num)) + "Auxiliary function to create and return a scanner \(which is +actually a closure). Used by CREATE-SCANNER." + (let ((starts-with-len (if (typep starts-with 'str) + (len starts-with))) + (starts-with-everything (typep starts-with 'everything))) + (cond + ;; this COND statement dispatches on the different versions we + ;; have for ADVANCE-FN and creates different closures for each; + ;; note that you see only the bodies of ADVANCE-FN below - the + ;; actual scanner is defined in INSERT-ADVANCE-FN above; (we + ;; could have done this with closures instead of macrology but + ;; would have consed a lot more) + ((and start-string-test end-string-test end-string-offset) + ;; we know that the regular expression has constant start and + ;; end strings and we know the end string's offset (from the + ;; left) + (insert-advance-fn + (advance-fn (pos) + (declare (type fixnum end-string-offset starts-with-len) + (type function start-string-test end-string-test)) + (loop + (unless (setq pos (funcall start-string-test pos)) + ;; give up completely if we can't find a start string + ;; candidate + (return-from scan nil)) + (locally + ;; from here we know that POS is a FIXNUM + (declare (type fixnum pos)) + (when (= pos (- (the fixnum *end-string-pos*) end-string-offset)) + ;; if we already found an end string candidate the + ;; position of which matches the start string + ;; candidate we're done + (return-from advance-fn pos)) + (let ((try-pos (+ pos starts-with-len))) + ;; otherwise try (again) to find an end string + ;; candidate which starts behind the start string + ;; candidate + (loop + (unless (setq *end-string-pos* + (funcall end-string-test try-pos)) + ;; no end string candidate found, so give up + (return-from scan nil)) + ;; NEW-POS is where we should start scanning + ;; according to the end string candidate + (let ((new-pos (- (the fixnum *end-string-pos*) + end-string-offset))) + (declare (type fixnum new-pos *end-string-pos*)) + (cond ((= new-pos pos) + ;; if POS and NEW-POS are equal then the + ;; two candidates agree so we're fine + (return-from advance-fn pos)) + ((> new-pos pos) + ;; if NEW-POS is further to the right we + ;; advance POS and try again, i.e. we go + ;; back to the start of the outer LOOP + (setq pos new-pos) + ;; this means "return from inner LOOP" + (return)) + (t + ;; otherwise NEW-POS is smaller than POS, + ;; so we have to redo the inner LOOP to + ;; find another end string candidate + ;; further to the right + (setq try-pos (1+ *end-string-pos*)))))))))))) + ((and starts-with-everything end-string-test end-string-offset) + ;; we know that the regular expression starts with ".*" (which + ;; is not in single-line-mode, see CREATE-SCANNER-AUX) and ends + ;; with a constant end string and we know the end string's + ;; offset (from the left) + (insert-advance-fn + (advance-fn (pos) + (declare (type fixnum end-string-offset) + (type function end-string-test)) + (loop + (unless (setq pos (newline-skipper pos)) + ;; if we can't find a #\Newline we give up immediately + (return-from scan nil)) + (locally + ;; from here we know that POS is a FIXNUM + (declare (type fixnum pos)) + (when (= pos (- (the fixnum *end-string-pos*) end-string-offset)) + ;; if we already found an end string candidate the + ;; position of which matches the place behind the + ;; #\Newline we're done + (return-from advance-fn pos)) + (let ((try-pos pos)) + ;; otherwise try (again) to find an end string + ;; candidate which starts behind the #\Newline + (loop + (unless (setq *end-string-pos* + (funcall end-string-test try-pos)) + ;; no end string candidate found, so we give up + (return-from scan nil)) + ;; NEW-POS is where we should start scanning + ;; according to the end string candidate + (let ((new-pos (- (the fixnum *end-string-pos*) + end-string-offset))) + (declare (type fixnum new-pos *end-string-pos*)) + (cond ((= new-pos pos) + ;; if POS and NEW-POS are equal then the + ;; the end string candidate agrees with + ;; the #\Newline so we're fine + (return-from advance-fn pos)) + ((> new-pos pos) + ;; if NEW-POS is further to the right we + ;; advance POS and try again, i.e. we go + ;; back to the start of the outer LOOP + (setq pos new-pos) + ;; this means "return from inner LOOP" + (return)) + (t + ;; otherwise NEW-POS is smaller than POS, + ;; so we have to redo the inner LOOP to + ;; find another end string candidate + ;; further to the right + (setq try-pos (1+ *end-string-pos*)))))))))))) + ((and start-string-test end-string-test) + ;; we know that the regular expression has constant start and + ;; end strings; similar to the first case but we only need to + ;; check for the end string, it doesn't provide enough + ;; information to advance POS + (insert-advance-fn + (advance-fn (pos) + (declare (type function start-string-test end-string-test)) + (unless (setq pos (funcall start-string-test pos)) + (return-from scan nil)) + (if (<= (the fixnum pos) + (the fixnum *end-string-pos*)) + (return-from advance-fn pos)) + (unless (setq *end-string-pos* (funcall end-string-test pos)) + (return-from scan nil)) + pos))) + ((and starts-with-everything end-string-test) + ;; we know that the regular expression starts with ".*" (which + ;; is not in single-line-mode, see CREATE-SCANNER-AUX) and ends + ;; with a constant end string; similar to the second case but we + ;; only need to check for the end string, it doesn't provide + ;; enough information to advance POS + (insert-advance-fn + (advance-fn (pos) + (declare (type function end-string-test)) + (unless (setq pos (newline-skipper pos)) + (return-from scan nil)) + (if (<= (the fixnum pos) + (the fixnum *end-string-pos*)) + (return-from advance-fn pos)) + (unless (setq *end-string-pos* (funcall end-string-test pos)) + (return-from scan nil)) + pos))) + (start-string-test + ;; just check for constant start string candidate + (insert-advance-fn + (advance-fn (pos) + (declare (type function start-string-test)) + (unless (setq pos (funcall start-string-test pos)) + (return-from scan nil)) + pos))) + (starts-with-everything + ;; just advance POS with NEWLINE-SKIPPER + (insert-advance-fn + (advance-fn (pos) + (unless (setq pos (newline-skipper pos)) + (return-from scan nil)) + pos))) + (end-string-test + ;; just check for the next end string candidate if POS has + ;; advanced beyond the last one + (insert-advance-fn + (advance-fn (pos) + (declare (type function end-string-test)) + (if (<= (the fixnum pos) + (the fixnum *end-string-pos*)) + (return-from advance-fn pos)) + (unless (setq *end-string-pos* (funcall end-string-test pos)) + (return-from scan nil)) + pos))) + (t + ;; not enough optimization information about the regular + ;; expression to optimize so we just return POS + (insert-advance-fn + (advance-fn (pos) + pos)))))) \ No newline at end of file diff --git a/practicals/libraries/cl-ppcre-1.2.3/specials.lisp b/practicals/libraries/cl-ppcre-1.2.3/specials.lisp new file mode 100644 index 0000000..86d60d4 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/specials.lisp @@ -0,0 +1,126 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/specials.lisp,v 1.19 2004/04/22 18:50:16 edi Exp $ + +;;; globally declared special variables + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre) + +;;; special variables used by the lexer/parser combo + +(defvar *extended-mode-p* nil + "Whether the parser will start in extended mode.") +(declaim (type boolean *extended-mode-p*)) + +;;; special variables used by the SCAN function and the matchers + +(defvar *string* "" + "The string which is currently scanned by SCAN. +Will always be coerced to a SIMPLE-STRING.") +(declaim (type simple-string *string*)) + +(defvar *start-pos* 0 + "Where to start scanning within *STRING*.") +(declaim (type fixnum *start-pos*)) + +(defvar *real-start-pos* nil + "The real start of *STRING*. This is for repeated scans and is only used internally.") +(declaim (type (or null fixnum) *real-start-pos*)) + +(defvar *end-pos* 0 + "Where to stop scanning within *STRING*.") +(declaim (type fixnum *end-pos*)) + +(defvar *reg-starts* (make-array 0) + "An array which holds the start positions +of the current register candidates.") +(declaim (type simple-vector *reg-starts*)) + +(defvar *regs-maybe-start* (make-array 0) + "An array which holds the next start positions +of the current register candidates.") +(declaim (type simple-vector *regs-maybe-start*)) + +(defvar *reg-ends* (make-array 0) + "An array which holds the end positions +of the current register candidates.") +(declaim (type simple-vector *reg-ends*)) + +(defvar *end-string-pos* nil + "Start of the next possible end-string candidate.") + +(defvar *rep-num* 0 + "Counts the number of \"complicated\" repetitions while the matchers +are built.") +(declaim (type fixnum *rep-num*)) + +(defvar *zero-length-num* 0 + "Counts the number of repetitions the inner regexes of which may +have zero-length while the matchers are built.") +(declaim (type fixnum *zero-length-num*)) + +(defvar *repeat-counters* (make-array 0 + :initial-element 0 + :element-type 'fixnum) + "An array to keep track of how often +repetitive patterns have been tested already.") +(declaim (type (array fixnum (*)) *repeat-counters*)) + +(defvar *last-pos-stores* (make-array 0) + "An array to keep track of the last positions +where we saw repetitive patterns. +Only used for patterns which might have zero length.") +(declaim (type simple-vector *last-pos-stores*)) + +(defvar *use-bmh-matchers* t + "Whether the scanners created by CREATE-SCANNER should use the \(fast +but large) Boyer-Moore-Horspool matchers.") + +(defvar *allow-quoting* nil + "Whether the parser should support Perl's \\Q and \\E.") + +(pushnew :cl-ppcre *features*) + +;; stuff for Nikodemus Siivola's HYPERDOC +;; see +;; and + +(defvar *hyperdoc-base-uri* "http://weitz.de/cl-ppcre/") + +(let ((exported-symbols-alist + (loop for symbol being the external-symbols of :cl-ppcre + collect (cons symbol + (concatenate 'string + "#" + (string-downcase symbol)))))) + (defun hyperdoc-lookup (symbol type) + (declare (ignore type)) + (cdr (assoc symbol + exported-symbols-alist + :test #'eq)))) + \ No newline at end of file diff --git a/practicals/libraries/cl-ppcre-1.2.3/testdata b/practicals/libraries/cl-ppcre-1.2.3/testdata new file mode 100644 index 0000000..925d0ef --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/testdata @@ -0,0 +1,14288 @@ +(1 "\"the quick brown fox\" =~ /the quick brown fox/" "the quick brown fox" nil nil nil nil "the quick brown fox" nil 1 0 "the quick brown fox" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(2 "\"The quick brown FOX\" =~ /the quick brown fox/" "the quick brown fox" nil nil nil nil "The quick brown FOX" nil 1 0 nil nil) +(3 "\"What do you know about the quick brown fox?\" =~ /the quick brown fox/" "the quick brown fox" nil nil nil nil "What do you know about the quick brown fox?" nil 1 0 "the quick brown fox" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(4 "\"What do you know about THE QUICK BROWN FOX?\" =~ /the quick brown fox/" "the quick brown fox" nil nil nil nil "What do you know about THE QUICK BROWN FOX?" nil 1 0 nil nil) +(5 "\"the quick brown fox\" =~ /The quick brown fox/i" "The quick brown fox" t nil nil nil "the quick brown fox" nil 1 0 "the quick brown fox" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(6 "\"The quick brown FOX\" =~ /The quick brown fox/i" "The quick brown fox" t nil nil nil "The quick brown FOX" nil 1 0 "The quick brown FOX" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(7 "\"What do you know about the quick brown fox?\" =~ /The quick brown fox/i" "The quick brown fox" t nil nil nil "What do you know about the quick brown fox?" nil 1 0 "the quick brown fox" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(8 "\"What do you know about THE QUICK BROWN FOX?\" =~ /The quick brown fox/i" "The quick brown fox" t nil nil nil "What do you know about THE QUICK BROWN FOX?" nil 1 0 "THE QUICK BROWN FOX" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(9 "\"abcd\\t\\n\\r\\f\\a\\e9;\\$\\\\?caxyz\" =~ /abcd\\t\\n\\r\\f\\a\\e\\071\\x3b\\$\\\\\\?caxyz/" "abcd\\t\\n\\r\\f\\a\\e\\071\\x3b\\$\\\\\\?caxyz" nil nil nil nil ("abcd" 9 10 13 12 7 27 "9;$\\?caxyz") nil 1 0 ("abcd" 9 10 13 12 7 27 "9;$\\?caxyz") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(10 "\"abxyzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "abxyzpqrrrabbxyyyypqAzz" nil 1 0 "abxyzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(11 "\"abxyzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "abxyzpqrrrabbxyyyypqAzz" nil 1 0 "abxyzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(12 "\"aabxyzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aabxyzpqrrrabbxyyyypqAzz" nil 1 0 "aabxyzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(13 "\"aaabxyzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabxyzpqrrrabbxyyyypqAzz" nil 1 0 "aaabxyzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(14 "\"aaaabxyzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaaabxyzpqrrrabbxyyyypqAzz" nil 1 0 "aaaabxyzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(15 "\"abcxyzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "abcxyzpqrrrabbxyyyypqAzz" nil 1 0 "abcxyzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(16 "\"aabcxyzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aabcxyzpqrrrabbxyyyypqAzz" nil 1 0 "aabcxyzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(17 "\"aaabcxyzpqrrrabbxyyyypAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabcxyzpqrrrabbxyyyypAzz" nil 1 0 "aaabcxyzpqrrrabbxyyyypAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(18 "\"aaabcxyzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabcxyzpqrrrabbxyyyypqAzz" nil 1 0 "aaabcxyzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(19 "\"aaabcxyzpqrrrabbxyyyypqqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabcxyzpqrrrabbxyyyypqqAzz" nil 1 0 "aaabcxyzpqrrrabbxyyyypqqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(20 "\"aaabcxyzpqrrrabbxyyyypqqqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabcxyzpqrrrabbxyyyypqqqAzz" nil 1 0 "aaabcxyzpqrrrabbxyyyypqqqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(21 "\"aaabcxyzpqrrrabbxyyyypqqqqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabcxyzpqrrrabbxyyyypqqqqAzz" nil 1 0 "aaabcxyzpqrrrabbxyyyypqqqqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(22 "\"aaabcxyzpqrrrabbxyyyypqqqqqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabcxyzpqrrrabbxyyyypqqqqqAzz" nil 1 0 "aaabcxyzpqrrrabbxyyyypqqqqqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(23 "\"aaabcxyzpqrrrabbxyyyypqqqqqqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabcxyzpqrrrabbxyyyypqqqqqqAzz" nil 1 0 "aaabcxyzpqrrrabbxyyyypqqqqqqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(24 "\"aaaabcxyzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaaabcxyzpqrrrabbxyyyypqAzz" nil 1 0 "aaaabcxyzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(25 "\"abxyzzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "abxyzzpqrrrabbxyyyypqAzz" nil 1 0 "abxyzzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(26 "\"aabxyzzzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aabxyzzzpqrrrabbxyyyypqAzz" nil 1 0 "aabxyzzzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(27 "\"aaabxyzzzzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabxyzzzzpqrrrabbxyyyypqAzz" nil 1 0 "aaabxyzzzzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(28 "\"aaaabxyzzzzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaaabxyzzzzpqrrrabbxyyyypqAzz" nil 1 0 "aaaabxyzzzzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(29 "\"abcxyzzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "abcxyzzpqrrrabbxyyyypqAzz" nil 1 0 "abcxyzzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(30 "\"aabcxyzzzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aabcxyzzzpqrrrabbxyyyypqAzz" nil 1 0 "aabcxyzzzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(31 "\"aaabcxyzzzzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabcxyzzzzpqrrrabbxyyyypqAzz" nil 1 0 "aaabcxyzzzzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(32 "\"aaaabcxyzzzzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaaabcxyzzzzpqrrrabbxyyyypqAzz" nil 1 0 "aaaabcxyzzzzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(33 "\"aaaabcxyzzzzpqrrrabbbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaaabcxyzzzzpqrrrabbbxyyyypqAzz" nil 1 0 "aaaabcxyzzzzpqrrrabbbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(34 "\"aaaabcxyzzzzpqrrrabbbxyyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaaabcxyzzzzpqrrrabbbxyyyyypqAzz" nil 1 0 "aaaabcxyzzzzpqrrrabbbxyyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(35 "\"aaabcxyzpqrrrabbxyyyypABzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabcxyzpqrrrabbxyyyypABzz" nil 1 0 "aaabcxyzpqrrrabbxyyyypABzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(36 "\"aaabcxyzpqrrrabbxyyyypABBzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabcxyzpqrrrabbxyyyypABBzz" nil 1 0 "aaabcxyzpqrrrabbxyyyypABBzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(37 "\">>>aaabxyzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil ">>>aaabxyzpqrrrabbxyyyypqAzz" nil 1 0 "aaabxyzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(38 "\">aaaabxyzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil ">aaaabxyzpqrrrabbxyyyypqAzz" nil 1 0 "aaaabxyzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(39 "\">>>>abcxyzpqrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil ">>>>abcxyzpqrrrabbxyyyypqAzz" nil 1 0 "abcxyzpqrrrabbxyyyypqAzz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(40 "\"abxyzpqrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "abxyzpqrrabbxyyyypqAzz" nil 1 0 nil nil) +(41 "\"abxyzpqrrrrabbxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "abxyzpqrrrrabbxyyyypqAzz" nil 1 0 nil nil) +(42 "\"abxyzpqrrrabxyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "abxyzpqrrrabxyyyypqAzz" nil 1 0 nil nil) +(43 "\"aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz" nil 1 0 nil nil) +(44 "\"aaaabcxyzzzzpqrrrabbbxyyypqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaaabcxyzzzzpqrrrabbbxyyypqAzz" nil 1 0 nil nil) +(45 "\"aaabcxyzpqrrrabbxyyyypqqqqqqqAzz\" =~ /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/" "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" nil nil nil nil "aaabcxyzpqrrrabbxyyyypqqqqqqqAzz" nil 1 0 nil nil) +(46 "\"abczz\" =~ /^(abc){1,2}zz/" "^(abc){1,2}zz" nil nil nil nil "abczz" nil 1 0 "abczz" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(47 "\"abcabczz\" =~ /^(abc){1,2}zz/" "^(abc){1,2}zz" nil nil nil nil "abcabczz" nil 1 0 "abcabczz" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(48 "\"zz\" =~ /^(abc){1,2}zz/" "^(abc){1,2}zz" nil nil nil nil "zz" nil 1 0 nil nil) +(49 "\"abcabcabczz\" =~ /^(abc){1,2}zz/" "^(abc){1,2}zz" nil nil nil nil "abcabcabczz" nil 1 0 nil nil) +(50 "\">>abczz\" =~ /^(abc){1,2}zz/" "^(abc){1,2}zz" nil nil nil nil ">>abczz" nil 1 0 nil nil) +(51 "\"bc\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "bc" nil 1 0 "bc" ("b" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(52 "\"bbc\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "bbc" nil 1 0 "bbc" ("b" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(53 "\"bbbc\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "bbbc" nil 1 0 "bbbc" ("bb" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(54 "\"bac\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "bac" nil 1 0 "bac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(55 "\"bbac\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "bbac" nil 1 0 "bbac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(56 "\"aac\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "aac" nil 1 0 "aac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(57 "\"abbbbbbbbbbbc\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "abbbbbbbbbbbc" nil 1 0 "abbbbbbbbbbbc" ("bbbbbbbbbbb" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(58 "\"bbbbbbbbbbbac\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "bbbbbbbbbbbac" nil 1 0 "bbbbbbbbbbbac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(59 "\"aaac\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "aaac" nil 1 0 nil nil) +(60 "\"abbbbbbbbbbbac\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "abbbbbbbbbbbac" nil 1 0 nil nil) +(61 "\"bc\" =~ /^(b+|a){1,2}c/" "^(b+|a){1,2}c" nil nil nil nil "bc" nil 1 0 "bc" ("b" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(62 "\"bbc\" =~ /^(b+|a){1,2}c/" "^(b+|a){1,2}c" nil nil nil nil "bbc" nil 1 0 "bbc" ("bb" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(63 "\"bbbc\" =~ /^(b+|a){1,2}c/" "^(b+|a){1,2}c" nil nil nil nil "bbbc" nil 1 0 "bbbc" ("bbb" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(64 "\"bac\" =~ /^(b+|a){1,2}c/" "^(b+|a){1,2}c" nil nil nil nil "bac" nil 1 0 "bac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(65 "\"bbac\" =~ /^(b+|a){1,2}c/" "^(b+|a){1,2}c" nil nil nil nil "bbac" nil 1 0 "bbac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(66 "\"aac\" =~ /^(b+|a){1,2}c/" "^(b+|a){1,2}c" nil nil nil nil "aac" nil 1 0 "aac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(67 "\"abbbbbbbbbbbc\" =~ /^(b+|a){1,2}c/" "^(b+|a){1,2}c" nil nil nil nil "abbbbbbbbbbbc" nil 1 0 "abbbbbbbbbbbc" ("bbbbbbbbbbb" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(68 "\"bbbbbbbbbbbac\" =~ /^(b+|a){1,2}c/" "^(b+|a){1,2}c" nil nil nil nil "bbbbbbbbbbbac" nil 1 0 "bbbbbbbbbbbac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(69 "\"aaac\" =~ /^(b+|a){1,2}c/" "^(b+|a){1,2}c" nil nil nil nil "aaac" nil 1 0 nil nil) +(70 "\"abbbbbbbbbbbac\" =~ /^(b+|a){1,2}c/" "^(b+|a){1,2}c" nil nil nil nil "abbbbbbbbbbbac" nil 1 0 nil nil) +(71 "\"bbc\" =~ /^(b+|a){1,2}?bc/" "^(b+|a){1,2}?bc" nil nil nil nil "bbc" nil 1 0 "bbc" ("b" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(72 "\"babc\" =~ /^(b*|ba){1,2}?bc/" "^(b*|ba){1,2}?bc" nil nil nil nil "babc" nil 1 0 "babc" ("ba" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(73 "\"bbabc\" =~ /^(b*|ba){1,2}?bc/" "^(b*|ba){1,2}?bc" nil nil nil nil "bbabc" nil 1 0 "bbabc" ("ba" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(74 "\"bababc\" =~ /^(b*|ba){1,2}?bc/" "^(b*|ba){1,2}?bc" nil nil nil nil "bababc" nil 1 0 "bababc" ("ba" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(75 "\"bababbc\" =~ /^(b*|ba){1,2}?bc/" "^(b*|ba){1,2}?bc" nil nil nil nil "bababbc" nil 1 0 nil nil) +(76 "\"babababc\" =~ /^(b*|ba){1,2}?bc/" "^(b*|ba){1,2}?bc" nil nil nil nil "babababc" nil 1 0 nil nil) +(77 "\"babc\" =~ /^(ba|b*){1,2}?bc/" "^(ba|b*){1,2}?bc" nil nil nil nil "babc" nil 1 0 "babc" ("ba" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(78 "\"bbabc\" =~ /^(ba|b*){1,2}?bc/" "^(ba|b*){1,2}?bc" nil nil nil nil "bbabc" nil 1 0 "bbabc" ("ba" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(79 "\"bababc\" =~ /^(ba|b*){1,2}?bc/" "^(ba|b*){1,2}?bc" nil nil nil nil "bababc" nil 1 0 "bababc" ("ba" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(80 "\"bababbc\" =~ /^(ba|b*){1,2}?bc/" "^(ba|b*){1,2}?bc" nil nil nil nil "bababbc" nil 1 0 nil nil) +(81 "\"babababc\" =~ /^(ba|b*){1,2}?bc/" "^(ba|b*){1,2}?bc" nil nil nil nil "babababc" nil 1 0 nil nil) +(82 "\"\\x01\\x01\\e;z\" =~ /^\\ca\\cA\\c[\\c{\\c:/" "^\\ca\\cA\\c[\\c{\\c:" nil nil nil nil ("" 1 1 27 ";z") nil 1 0 ("" 1 1 27 ";z") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(83 "\"athing\" =~ /^[ab\\]cde]/" "^[ab\\]cde]" nil nil nil nil "athing" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(84 "\"bthing\" =~ /^[ab\\]cde]/" "^[ab\\]cde]" nil nil nil nil "bthing" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(85 "\"]thing\" =~ /^[ab\\]cde]/" "^[ab\\]cde]" nil nil nil nil "]thing" nil 1 0 "]" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(86 "\"cthing\" =~ /^[ab\\]cde]/" "^[ab\\]cde]" nil nil nil nil "cthing" nil 1 0 "c" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(87 "\"dthing\" =~ /^[ab\\]cde]/" "^[ab\\]cde]" nil nil nil nil "dthing" nil 1 0 "d" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(88 "\"ething\" =~ /^[ab\\]cde]/" "^[ab\\]cde]" nil nil nil nil "ething" nil 1 0 "e" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(89 "\"fthing\" =~ /^[ab\\]cde]/" "^[ab\\]cde]" nil nil nil nil "fthing" nil 1 0 nil nil) +(90 "\"[thing\" =~ /^[ab\\]cde]/" "^[ab\\]cde]" nil nil nil nil "[thing" nil 1 0 nil nil) +(91 "\"\\\\thing\" =~ /^[ab\\]cde]/" "^[ab\\]cde]" nil nil nil nil "\\thing" nil 1 0 nil nil) +(92 "\"]thing\" =~ /^[]cde]/" "^[]cde]" nil nil nil nil "]thing" nil 1 0 "]" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(93 "\"cthing\" =~ /^[]cde]/" "^[]cde]" nil nil nil nil "cthing" nil 1 0 "c" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(94 "\"dthing\" =~ /^[]cde]/" "^[]cde]" nil nil nil nil "dthing" nil 1 0 "d" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(95 "\"ething\" =~ /^[]cde]/" "^[]cde]" nil nil nil nil "ething" nil 1 0 "e" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(96 "\"athing\" =~ /^[]cde]/" "^[]cde]" nil nil nil nil "athing" nil 1 0 nil nil) +(97 "\"fthing\" =~ /^[]cde]/" "^[]cde]" nil nil nil nil "fthing" nil 1 0 nil nil) +(98 "\"fthing\" =~ /^[^ab\\]cde]/" "^[^ab\\]cde]" nil nil nil nil "fthing" nil 1 0 "f" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(99 "\"[thing\" =~ /^[^ab\\]cde]/" "^[^ab\\]cde]" nil nil nil nil "[thing" nil 1 0 "[" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(100 "\"\\\\thing\" =~ /^[^ab\\]cde]/" "^[^ab\\]cde]" nil nil nil nil "\\thing" nil 1 0 "\\" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(101 "\"athing\" =~ /^[^ab\\]cde]/" "^[^ab\\]cde]" nil nil nil nil "athing" nil 1 0 nil nil) +(102 "\"bthing\" =~ /^[^ab\\]cde]/" "^[^ab\\]cde]" nil nil nil nil "bthing" nil 1 0 nil nil) +(103 "\"]thing\" =~ /^[^ab\\]cde]/" "^[^ab\\]cde]" nil nil nil nil "]thing" nil 1 0 nil nil) +(104 "\"cthing\" =~ /^[^ab\\]cde]/" "^[^ab\\]cde]" nil nil nil nil "cthing" nil 1 0 nil nil) +(105 "\"dthing\" =~ /^[^ab\\]cde]/" "^[^ab\\]cde]" nil nil nil nil "dthing" nil 1 0 nil nil) +(106 "\"ething\" =~ /^[^ab\\]cde]/" "^[^ab\\]cde]" nil nil nil nil "ething" nil 1 0 nil nil) +(107 "\"athing\" =~ /^[^]cde]/" "^[^]cde]" nil nil nil nil "athing" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(108 "\"fthing\" =~ /^[^]cde]/" "^[^]cde]" nil nil nil nil "fthing" nil 1 0 "f" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(109 "\"]thing\" =~ /^[^]cde]/" "^[^]cde]" nil nil nil nil "]thing" nil 1 0 nil nil) +(110 "\"cthing\" =~ /^[^]cde]/" "^[^]cde]" nil nil nil nil "cthing" nil 1 0 nil nil) +(111 "\"dthing\" =~ /^[^]cde]/" "^[^]cde]" nil nil nil nil "dthing" nil 1 0 nil nil) +(112 "\"ething\" =~ /^[^]cde]/" "^[^]cde]" nil nil nil nil "ething" nil 1 0 nil nil) +(113 ("\"" 129 "\" =~ /^\\" 129 "/") "^\\" nil nil nil nil ("" 129) nil 1 0 ("" 129) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(114 ("\"" 255 "\" =~ /^" 255 "/") "^ÿ" nil nil nil nil ("" 255) nil 1 0 ("" 255) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(115 "\"0\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "0" nil 1 0 "0" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(116 "\"1\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "1" nil 1 0 "1" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(117 "\"2\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "2" nil 1 0 "2" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(118 "\"3\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "3" nil 1 0 "3" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(119 "\"4\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "4" nil 1 0 "4" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(120 "\"5\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "5" nil 1 0 "5" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(121 "\"6\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "6" nil 1 0 "6" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(122 "\"7\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "7" nil 1 0 "7" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(123 "\"8\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "8" nil 1 0 "8" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(124 "\"9\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "9" nil 1 0 "9" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(125 "\"10\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "10" nil 1 0 "10" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(126 "\"100\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "100" nil 1 0 "100" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(127 "\"abc\" =~ /^[0-9]+$/" "^[0-9]+$" nil nil nil nil "abc" nil 1 0 nil nil) +(128 "\"enter\" =~ /^.*nter/" "^.*nter" nil nil nil nil "enter" nil 1 0 "enter" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(129 "\"inter\" =~ /^.*nter/" "^.*nter" nil nil nil nil "inter" nil 1 0 "inter" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(130 "\"uponter\" =~ /^.*nter/" "^.*nter" nil nil nil nil "uponter" nil 1 0 "uponter" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(131 "\"xxx0\" =~ /^xxx[0-9]+$/" "^xxx[0-9]+$" nil nil nil nil "xxx0" nil 1 0 "xxx0" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(132 "\"xxx1234\" =~ /^xxx[0-9]+$/" "^xxx[0-9]+$" nil nil nil nil "xxx1234" nil 1 0 "xxx1234" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(133 "\"xxx\" =~ /^xxx[0-9]+$/" "^xxx[0-9]+$" nil nil nil nil "xxx" nil 1 0 nil nil) +(134 "\"x123\" =~ /^.+[0-9][0-9][0-9]$/" "^.+[0-9][0-9][0-9]$" nil nil nil nil "x123" nil 1 0 "x123" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(135 "\"xx123\" =~ /^.+[0-9][0-9][0-9]$/" "^.+[0-9][0-9][0-9]$" nil nil nil nil "xx123" nil 1 0 "xx123" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(136 "\"123456\" =~ /^.+[0-9][0-9][0-9]$/" "^.+[0-9][0-9][0-9]$" nil nil nil nil "123456" nil 1 0 "123456" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(137 "\"123\" =~ /^.+[0-9][0-9][0-9]$/" "^.+[0-9][0-9][0-9]$" nil nil nil nil "123" nil 1 0 nil nil) +(138 "\"x1234\" =~ /^.+[0-9][0-9][0-9]$/" "^.+[0-9][0-9][0-9]$" nil nil nil nil "x1234" nil 1 0 "x1234" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(139 "\"x123\" =~ /^.+?[0-9][0-9][0-9]$/" "^.+?[0-9][0-9][0-9]$" nil nil nil nil "x123" nil 1 0 "x123" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(140 "\"xx123\" =~ /^.+?[0-9][0-9][0-9]$/" "^.+?[0-9][0-9][0-9]$" nil nil nil nil "xx123" nil 1 0 "xx123" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(141 "\"123456\" =~ /^.+?[0-9][0-9][0-9]$/" "^.+?[0-9][0-9][0-9]$" nil nil nil nil "123456" nil 1 0 "123456" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(142 "\"123\" =~ /^.+?[0-9][0-9][0-9]$/" "^.+?[0-9][0-9][0-9]$" nil nil nil nil "123" nil 1 0 nil nil) +(143 "\"x1234\" =~ /^.+?[0-9][0-9][0-9]$/" "^.+?[0-9][0-9][0-9]$" nil nil nil nil "x1234" nil 1 0 "x1234" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(144 "\"abc!pqr=apquxz.ixr.zzz.ac.uk\" =~ /^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$/" "^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$" nil nil nil nil "abc!pqr=apquxz.ixr.zzz.ac.uk" nil 1 0 "abc!pqr=apquxz.ixr.zzz.ac.uk" ("abc" "pqr" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(145 "\"!pqr=apquxz.ixr.zzz.ac.uk\" =~ /^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$/" "^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$" nil nil nil nil "!pqr=apquxz.ixr.zzz.ac.uk" nil 1 0 nil nil) +(146 "\"abc!=apquxz.ixr.zzz.ac.uk\" =~ /^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$/" "^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$" nil nil nil nil "abc!=apquxz.ixr.zzz.ac.uk" nil 1 0 nil nil) +(147 "\"abc!pqr=apquxz:ixr.zzz.ac.uk\" =~ /^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$/" "^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$" nil nil nil nil "abc!pqr=apquxz:ixr.zzz.ac.uk" nil 1 0 nil nil) +(148 "\"abc!pqr=apquxz.ixr.zzz.ac.ukk\" =~ /^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$/" "^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$" nil nil nil nil "abc!pqr=apquxz.ixr.zzz.ac.ukk" nil 1 0 nil nil) +(149 "\"Well, we need a colon: somewhere\" =~ /:/" ":" nil nil nil nil "Well, we need a colon: somewhere" nil 1 0 ":" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(150 "\"Fail if we don't\" =~ /:/" ":" nil nil nil nil "Fail if we don't" nil 1 0 nil nil) +(151 "\"0abc\" =~ /([\\da-f:]+)$/i" "([\\da-f:]+)$" t nil nil nil "0abc" nil 1 0 "0abc" ("0abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(152 "\"abc\" =~ /([\\da-f:]+)$/i" "([\\da-f:]+)$" t nil nil nil "abc" nil 1 0 "abc" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(153 "\"fed\" =~ /([\\da-f:]+)$/i" "([\\da-f:]+)$" t nil nil nil "fed" nil 1 0 "fed" ("fed" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(154 "\"E\" =~ /([\\da-f:]+)$/i" "([\\da-f:]+)$" t nil nil nil "E" nil 1 0 "E" ("E" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(155 "\"::\" =~ /([\\da-f:]+)$/i" "([\\da-f:]+)$" t nil nil nil "::" nil 1 0 "::" ("::" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(156 "\"5f03:12C0::932e\" =~ /([\\da-f:]+)$/i" "([\\da-f:]+)$" t nil nil nil "5f03:12C0::932e" nil 1 0 "5f03:12C0::932e" ("5f03:12C0::932e" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(157 "\"fed def\" =~ /([\\da-f:]+)$/i" "([\\da-f:]+)$" t nil nil nil "fed def" nil 1 0 "def" ("def" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(158 "\"Any old stuff\" =~ /([\\da-f:]+)$/i" "([\\da-f:]+)$" t nil nil nil "Any old stuff" nil 1 0 "ff" ("ff" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(159 "\"0zzz\" =~ /([\\da-f:]+)$/i" "([\\da-f:]+)$" t nil nil nil "0zzz" nil 1 0 nil nil) +(160 "\"gzzz\" =~ /([\\da-f:]+)$/i" "([\\da-f:]+)$" t nil nil nil "gzzz" nil 1 0 nil nil) +(161 "\"fed\\x20\" =~ /([\\da-f:]+)$/i" "([\\da-f:]+)$" t nil nil nil "fed " nil 1 0 nil nil) +(162 "\"Any old rubbish\" =~ /([\\da-f:]+)$/i" "([\\da-f:]+)$" t nil nil nil "Any old rubbish" nil 1 0 nil nil) +(163 "\".1.2.3\" =~ /^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/" "^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$" nil nil nil nil ".1.2.3" nil 1 0 ".1.2.3" ("1" "2" "3" nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(164 "\"A.12.123.0\" =~ /^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/" "^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$" nil nil nil nil "A.12.123.0" nil 1 0 "A.12.123.0" ("12" "123" "0" nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(165 "\".1.2.3333\" =~ /^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/" "^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$" nil nil nil nil ".1.2.3333" nil 1 0 nil nil) +(166 "\"1.2.3\" =~ /^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/" "^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$" nil nil nil nil "1.2.3" nil 1 0 nil nil) +(167 "\"1234.2.3\" =~ /^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/" "^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$" nil nil nil nil "1234.2.3" nil 1 0 nil nil) +(168 "\"1 IN SOA non-sp1 non-sp2(\" =~ /^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$/" "^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$" nil nil nil nil "1 IN SOA non-sp1 non-sp2(" nil 1 0 "1 IN SOA non-sp1 non-sp2(" ("1" "non-sp1" "non-sp2" nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(169 "\"1 IN SOA non-sp1 non-sp2 (\" =~ /^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$/" "^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$" nil nil nil nil "1 IN SOA non-sp1 non-sp2 (" nil 1 0 "1 IN SOA non-sp1 non-sp2 (" ("1" "non-sp1" "non-sp2" nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(170 "\"1IN SOA non-sp1 non-sp2(\" =~ /^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$/" "^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$" nil nil nil nil "1IN SOA non-sp1 non-sp2(" nil 1 0 nil nil) +(171 "\"a.\" =~ /^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$/" "^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$" nil nil nil nil "a." nil 1 0 "a." (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(172 "\"Z.\" =~ /^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$/" "^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$" nil nil nil nil "Z." nil 1 0 "Z." (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(173 "\"2.\" =~ /^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$/" "^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$" nil nil nil nil "2." nil 1 0 "2." (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(174 "\"ab-c.pq-r.\" =~ /^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$/" "^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$" nil nil nil nil "ab-c.pq-r." nil 1 0 "ab-c.pq-r." (".pq-r" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(175 "\"sxk.zzz.ac.uk.\" =~ /^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$/" "^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$" nil nil nil nil "sxk.zzz.ac.uk." nil 1 0 "sxk.zzz.ac.uk." (".uk" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(176 "\"x-.y-.\" =~ /^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$/" "^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$" nil nil nil nil "x-.y-." nil 1 0 "x-.y-." (".y-" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(177 "\"-abc.peq.\" =~ /^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$/" "^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$" nil nil nil nil "-abc.peq." nil 1 0 nil nil) +(178 "\"*.a\" =~ /^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$/" "^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$" nil nil nil nil "*.a" nil 1 0 "*.a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(179 "\"*.b0-a\" =~ /^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$/" "^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$" nil nil nil nil "*.b0-a" nil 1 0 "*.b0-a" ("0-a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(180 "\"*.c3-b.c\" =~ /^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$/" "^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$" nil nil nil nil "*.c3-b.c" nil 1 0 "*.c3-b.c" ("3-b" ".c" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(181 "\"*.c-a.b-c\" =~ /^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$/" "^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$" nil nil nil nil "*.c-a.b-c" nil 1 0 "*.c-a.b-c" ("-a" ".b-c" "-c" nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(182 "\"*.0\" =~ /^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$/" "^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$" nil nil nil nil "*.0" nil 1 0 nil nil) +(183 "\"*.a-\" =~ /^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$/" "^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$" nil nil nil nil "*.a-" nil 1 0 nil nil) +(184 "\"*.a-b.c-\" =~ /^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$/" "^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$" nil nil nil nil "*.a-b.c-" nil 1 0 nil nil) +(185 "\"*.c-a.0-c\" =~ /^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$/" "^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$" nil nil nil nil "*.c-a.0-c" nil 1 0 nil nil) +(186 "\"abde\" =~ /^(?=ab(de))(abd)(e)/" "^(?=ab(de))(abd)(e)" nil nil nil nil "abde" nil 1 0 "abde" ("de" "abd" "e" nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(187 "\"abdf\" =~ /^(?!(ab)de|x)(abd)(f)/" "^(?!(ab)de|x)(abd)(f)" nil nil nil nil "abdf" nil 1 0 "abdf" (nil "abd" "f" nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(188 "\"abcd\" =~ /^(?=(ab(cd)))(ab)/" "^(?=(ab(cd)))(ab)" nil nil nil nil "abcd" nil 1 0 "ab" ("abcd" "cd" "ab" nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(189 "\"a.b.c.d\" =~ /^[\\da-f](\\.[\\da-f])*$/i" "^[\\da-f](\\.[\\da-f])*$" t nil nil nil "a.b.c.d" nil 1 0 "a.b.c.d" (".d" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(190 "\"A.B.C.D\" =~ /^[\\da-f](\\.[\\da-f])*$/i" "^[\\da-f](\\.[\\da-f])*$" t nil nil nil "A.B.C.D" nil 1 0 "A.B.C.D" (".D" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(191 "\"a.b.c.1.2.3.C\" =~ /^[\\da-f](\\.[\\da-f])*$/i" "^[\\da-f](\\.[\\da-f])*$" t nil nil nil "a.b.c.1.2.3.C" nil 1 0 "a.b.c.1.2.3.C" (".C" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(192 "\"\\\"1234\\\"\" =~ /^\\\".*\\\"\\s*(;.*)?$/" "^\\\".*\\\"\\s*(;.*)?$" nil nil nil nil "\"1234\"" nil 1 0 "\"1234\"" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(193 "\"\\\"abcd\\\" ;\" =~ /^\\\".*\\\"\\s*(;.*)?$/" "^\\\".*\\\"\\s*(;.*)?$" nil nil nil nil "\"abcd\" ;" nil 1 0 "\"abcd\" ;" (";" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(194 "\"\\\"\\\" ; rhubarb\" =~ /^\\\".*\\\"\\s*(;.*)?$/" "^\\\".*\\\"\\s*(;.*)?$" nil nil nil nil "\"\" ; rhubarb" nil 1 0 "\"\" ; rhubarb" ("; rhubarb" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(195 "\"\\\"1234\\\" : things\" =~ /^\\\".*\\\"\\s*(;.*)?$/" "^\\\".*\\\"\\s*(;.*)?$" nil nil nil nil "\"1234\" : things" nil 1 0 nil nil) +(196 "\"\\\" =~ /^$/" "^$" nil nil nil nil "" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(197 "\"ab c\" =~ / ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)/x" " ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)" nil nil nil t "ab c" nil 1 0 "ab c" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(198 "\"abc\" =~ / ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)/x" " ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)" nil nil nil t "abc" nil 1 0 nil nil) +(199 "\"ab cde\" =~ / ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)/x" " ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)" nil nil nil t "ab cde" nil 1 0 nil nil) +(200 "\"ab c\" =~ /(?x) ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)/" "(?x) ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)" nil nil nil nil "ab c" nil 1 0 "ab c" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(201 "\"abc\" =~ /(?x) ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)/" "(?x) ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)" nil nil nil nil "abc" nil 1 0 nil nil) +(202 "\"ab cde\" =~ /(?x) ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)/" "(?x) ^ a (?# begins with a) b\\sc (?# then b c) $ (?# then end)" nil nil nil nil "ab cde" nil 1 0 nil nil) +(203 "\"a bcd\" =~ /^ a\\ b[c ]d $/x" "^ a\\ b[c ]d $" nil nil nil t "a bcd" nil 1 0 "a bcd" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(204 "\"a b d\" =~ /^ a\\ b[c ]d $/x" "^ a\\ b[c ]d $" nil nil nil t "a b d" nil 1 0 "a b d" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(205 "\"abcd\" =~ /^ a\\ b[c ]d $/x" "^ a\\ b[c ]d $" nil nil nil t "abcd" nil 1 0 nil nil) +(206 "\"ab d\" =~ /^ a\\ b[c ]d $/x" "^ a\\ b[c ]d $" nil nil nil t "ab d" nil 1 0 nil nil) +(207 "\"abcdefhijklm\" =~ /^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/" "^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$" nil nil nil nil "abcdefhijklm" nil 1 0 "abcdefhijklm" ("abc" "bc" "c" "def" "ef" "f" "hij" "ij" "j" "klm" "lm" "m" nil nil nil nil)) +(208 "\"abcdefhijklm\" =~ /^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$/" "^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$" nil nil nil nil "abcdefhijklm" nil 1 0 "abcdefhijklm" ("bc" "c" "ef" "f" "ij" "j" "lm" "m" nil nil nil nil nil nil nil nil)) +(209 "\"a+ Z0+\\x08\\n\\x1d\\x12\" =~ /^[\\w][\\W][\\s][\\S][\\d][\\D][\\b][\\n][\\c]][\\022]/" "^[\\w][\\W][\\s][\\S][\\d][\\D][\\b][\\n][\\c]][\\022]" nil nil nil nil ("a+ Z0+" 8 10 29 18) nil 1 0 ("a+ Z0+" 8 10 29 18) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(210 "\".^\\$(*+)|{?,?}\" =~ /^[.^$|()*+?{,}]+/" "^[.^$|()*+?{,}]+" nil nil nil nil ".^$(*+)|{?,?}" nil 1 0 ".^$(*+)|{?,?}" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(211 "\"z\" =~ /^a*\\w/" "^a*\\w" nil nil nil nil "z" nil 1 0 "z" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(212 "\"az\" =~ /^a*\\w/" "^a*\\w" nil nil nil nil "az" nil 1 0 "az" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(213 "\"aaaz\" =~ /^a*\\w/" "^a*\\w" nil nil nil nil "aaaz" nil 1 0 "aaaz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(214 "\"a\" =~ /^a*\\w/" "^a*\\w" nil nil nil nil "a" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(215 "\"aa\" =~ /^a*\\w/" "^a*\\w" nil nil nil nil "aa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(216 "\"aaaa\" =~ /^a*\\w/" "^a*\\w" nil nil nil nil "aaaa" nil 1 0 "aaaa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(217 "\"a+\" =~ /^a*\\w/" "^a*\\w" nil nil nil nil "a+" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(218 "\"aa+\" =~ /^a*\\w/" "^a*\\w" nil nil nil nil "aa+" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(219 "\"z\" =~ /^a*?\\w/" "^a*?\\w" nil nil nil nil "z" nil 1 0 "z" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(220 "\"az\" =~ /^a*?\\w/" "^a*?\\w" nil nil nil nil "az" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(221 "\"aaaz\" =~ /^a*?\\w/" "^a*?\\w" nil nil nil nil "aaaz" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(222 "\"a\" =~ /^a*?\\w/" "^a*?\\w" nil nil nil nil "a" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(223 "\"aa\" =~ /^a*?\\w/" "^a*?\\w" nil nil nil nil "aa" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(224 "\"aaaa\" =~ /^a*?\\w/" "^a*?\\w" nil nil nil nil "aaaa" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(225 "\"a+\" =~ /^a*?\\w/" "^a*?\\w" nil nil nil nil "a+" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(226 "\"aa+\" =~ /^a*?\\w/" "^a*?\\w" nil nil nil nil "aa+" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(227 "\"az\" =~ /^a+\\w/" "^a+\\w" nil nil nil nil "az" nil 1 0 "az" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(228 "\"aaaz\" =~ /^a+\\w/" "^a+\\w" nil nil nil nil "aaaz" nil 1 0 "aaaz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(229 "\"aa\" =~ /^a+\\w/" "^a+\\w" nil nil nil nil "aa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(230 "\"aaaa\" =~ /^a+\\w/" "^a+\\w" nil nil nil nil "aaaa" nil 1 0 "aaaa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(231 "\"aa+\" =~ /^a+\\w/" "^a+\\w" nil nil nil nil "aa+" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(232 "\"az\" =~ /^a+?\\w/" "^a+?\\w" nil nil nil nil "az" nil 1 0 "az" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(233 "\"aaaz\" =~ /^a+?\\w/" "^a+?\\w" nil nil nil nil "aaaz" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(234 "\"aa\" =~ /^a+?\\w/" "^a+?\\w" nil nil nil nil "aa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(235 "\"aaaa\" =~ /^a+?\\w/" "^a+?\\w" nil nil nil nil "aaaa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(236 "\"aa+\" =~ /^a+?\\w/" "^a+?\\w" nil nil nil nil "aa+" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(237 "\"1234567890\" =~ /^\\d{8}\\w{2,}/" "^\\d{8}\\w{2,}" nil nil nil nil "1234567890" nil 1 0 "1234567890" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(238 "\"12345678ab\" =~ /^\\d{8}\\w{2,}/" "^\\d{8}\\w{2,}" nil nil nil nil "12345678ab" nil 1 0 "12345678ab" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(239 "\"12345678__\" =~ /^\\d{8}\\w{2,}/" "^\\d{8}\\w{2,}" nil nil nil nil "12345678__" nil 1 0 "12345678__" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(240 "\"1234567\" =~ /^\\d{8}\\w{2,}/" "^\\d{8}\\w{2,}" nil nil nil nil "1234567" nil 1 0 nil nil) +(241 "\"uoie\" =~ /^[aeiou\\d]{4,5}$/" "^[aeiou\\d]{4,5}$" nil nil nil nil "uoie" nil 1 0 "uoie" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(242 "\"1234\" =~ /^[aeiou\\d]{4,5}$/" "^[aeiou\\d]{4,5}$" nil nil nil nil "1234" nil 1 0 "1234" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(243 "\"12345\" =~ /^[aeiou\\d]{4,5}$/" "^[aeiou\\d]{4,5}$" nil nil nil nil "12345" nil 1 0 "12345" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(244 "\"aaaaa\" =~ /^[aeiou\\d]{4,5}$/" "^[aeiou\\d]{4,5}$" nil nil nil nil "aaaaa" nil 1 0 "aaaaa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(245 "\"123456\" =~ /^[aeiou\\d]{4,5}$/" "^[aeiou\\d]{4,5}$" nil nil nil nil "123456" nil 1 0 nil nil) +(246 "\"uoie\" =~ /^[aeiou\\d]{4,5}?/" "^[aeiou\\d]{4,5}?" nil nil nil nil "uoie" nil 1 0 "uoie" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(247 "\"1234\" =~ /^[aeiou\\d]{4,5}?/" "^[aeiou\\d]{4,5}?" nil nil nil nil "1234" nil 1 0 "1234" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(248 "\"12345\" =~ /^[aeiou\\d]{4,5}?/" "^[aeiou\\d]{4,5}?" nil nil nil nil "12345" nil 1 0 "1234" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(249 "\"aaaaa\" =~ /^[aeiou\\d]{4,5}?/" "^[aeiou\\d]{4,5}?" nil nil nil nil "aaaaa" nil 1 0 "aaaa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(250 "\"123456\" =~ /^[aeiou\\d]{4,5}?/" "^[aeiou\\d]{4,5}?" nil nil nil nil "123456" nil 1 0 "1234" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(251 "\"abc=abcabc\" =~ /\\A(abc|def)=(\\1){2,3}\\Z/" "\\A(abc|def)=(\\1){2,3}\\Z" nil nil nil nil "abc=abcabc" nil 1 0 "abc=abcabc" ("abc" "abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(252 "\"def=defdefdef\" =~ /\\A(abc|def)=(\\1){2,3}\\Z/" "\\A(abc|def)=(\\1){2,3}\\Z" nil nil nil nil "def=defdefdef" nil 1 0 "def=defdefdef" ("def" "def" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(253 "\"abc=defdef\" =~ /\\A(abc|def)=(\\1){2,3}\\Z/" "\\A(abc|def)=(\\1){2,3}\\Z" nil nil nil nil "abc=defdef" nil 1 0 nil nil) +(254 "\"abcdefghijkcda2\" =~ /^(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\11*(\\3\\4)\\1(?#)2$/" "^(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\11*(\\3\\4)\\1(?#)2$" nil nil nil nil "abcdefghijkcda2" nil 1 0 "abcdefghijkcda2" ("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "cd" nil nil nil nil)) +(255 "\"abcdefghijkkkkcda2\" =~ /^(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\11*(\\3\\4)\\1(?#)2$/" "^(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\11*(\\3\\4)\\1(?#)2$" nil nil nil nil "abcdefghijkkkkcda2" nil 1 0 "abcdefghijkkkkcda2" ("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "cd" nil nil nil nil)) +(256 "\"cataract cataract23\" =~ /(cat(a(ract|tonic)|erpillar)) \\1()2(3)/" "(cat(a(ract|tonic)|erpillar)) \\1()2(3)" nil nil nil nil "cataract cataract23" nil 1 0 "cataract cataract23" ("cataract" "aract" "ract" "" "3" nil nil nil nil nil nil nil nil nil nil nil)) +(257 "\"catatonic catatonic23\" =~ /(cat(a(ract|tonic)|erpillar)) \\1()2(3)/" "(cat(a(ract|tonic)|erpillar)) \\1()2(3)" nil nil nil nil "catatonic catatonic23" nil 1 0 "catatonic catatonic23" ("catatonic" "atonic" "tonic" "" "3" nil nil nil nil nil nil nil nil nil nil nil)) +(258 "\"caterpillar caterpillar23\" =~ /(cat(a(ract|tonic)|erpillar)) \\1()2(3)/" "(cat(a(ract|tonic)|erpillar)) \\1()2(3)" nil nil nil nil "caterpillar caterpillar23" nil 1 0 "caterpillar caterpillar23" ("caterpillar" "erpillar" nil "" "3" nil nil nil nil nil nil nil nil nil nil nil)) +(259 "\"From abcd Mon Sep 01 12:33:02 1997\" =~ +/^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/" "^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]" nil nil nil nil "From abcd Mon Sep 01 12:33:02 1997" nil 1 0 "From abcd Mon Sep 01 12:33" ("abcd" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(260 "\"From abcd Mon Sep 01 12:33:02 1997\" =~ /^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d/" "^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d" nil nil nil nil "From abcd Mon Sep 01 12:33:02 1997" nil 1 0 "From abcd Mon Sep 01 12:33" ("Sep " nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(261 "\"From abcd Mon Sep 1 12:33:02 1997\" =~ /^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d/" "^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d" nil nil nil nil "From abcd Mon Sep 1 12:33:02 1997" nil 1 0 "From abcd Mon Sep 1 12:33" ("Sep " nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(262 "\"From abcd Sep 01 12:33:02 1997\" =~ /^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d/" "^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d" nil nil nil nil "From abcd Sep 01 12:33:02 1997" nil 1 0 nil nil) +(263 "\"12\\n34\" =~ /^12.34/s" "^12.34" nil nil t nil "12 +34" nil 1 0 "12 +34" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(264 "\"12\\r34\" =~ /^12.34/s" "^12.34" nil nil t nil ("12" 13 "34") nil 1 0 ("12" 13 "34") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(265 "\"the quick brown\\t fox\" =~ /\\w+(?=\\t)/" "\\w+(?=\\t)" nil nil nil nil ("the quick brown" 9 " fox") nil 1 0 "brown" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(266 "\"foobar is foolish see?\" =~ /foo(?!bar)(.*)/" "foo(?!bar)(.*)" nil nil nil nil "foobar is foolish see?" nil 1 0 "foolish see?" ("lish see?" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(267 "\"foobar crowbar etc\" =~ /(?:(?!foo)...|^.{0,2})bar(.*)/" "(?:(?!foo)...|^.{0,2})bar(.*)" nil nil nil nil "foobar crowbar etc" nil 1 0 "rowbar etc" (" etc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(268 "\"barrel\" =~ /(?:(?!foo)...|^.{0,2})bar(.*)/" "(?:(?!foo)...|^.{0,2})bar(.*)" nil nil nil nil "barrel" nil 1 0 "barrel" ("rel" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(269 "\"2barrel\" =~ /(?:(?!foo)...|^.{0,2})bar(.*)/" "(?:(?!foo)...|^.{0,2})bar(.*)" nil nil nil nil "2barrel" nil 1 0 "2barrel" ("rel" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(270 "\"A barrel\" =~ /(?:(?!foo)...|^.{0,2})bar(.*)/" "(?:(?!foo)...|^.{0,2})bar(.*)" nil nil nil nil "A barrel" nil 1 0 "A barrel" ("rel" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(271 "\"abc456\" =~ /^(\\D*)(?=\\d)(?!123)/" "^(\\D*)(?=\\d)(?!123)" nil nil nil nil "abc456" nil 1 0 "abc" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(272 "\"abc123\" =~ /^(\\D*)(?=\\d)(?!123)/" "^(\\D*)(?=\\d)(?!123)" nil nil nil nil "abc123" nil 1 0 nil nil) +(273 "\"1234\" =~ /^1234(?# test newlines + inside)/" "^1234(?# test newlines + inside)" nil nil nil nil "1234" nil 1 0 "1234" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(274 "\"1234\" =~ /^1234 #comment in extended re + /x" "^1234 #comment in extended re + " nil nil nil t "1234" nil 1 0 "1234" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(275 "\"abcd\" =~ /#rhubarb + abcd/x" "#rhubarb + abcd" nil nil nil t "abcd" nil 1 0 "abcd" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(276 "\"abcd\" =~ /^abcd#rhubarb/x" "^abcd#rhubarb" nil nil nil t "abcd" nil 1 0 "abcd" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(277 "\"aaab\" =~ /^(a)\\1{2,3}(.)/" "^(a)\\1{2,3}(.)" nil nil nil nil "aaab" nil 1 0 "aaab" ("a" "b" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(278 "\"aaaab\" =~ /^(a)\\1{2,3}(.)/" "^(a)\\1{2,3}(.)" nil nil nil nil "aaaab" nil 1 0 "aaaab" ("a" "b" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(279 "\"aaaaab\" =~ /^(a)\\1{2,3}(.)/" "^(a)\\1{2,3}(.)" nil nil nil nil "aaaaab" nil 1 0 "aaaaa" ("a" "a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(280 "\"aaaaaab\" =~ /^(a)\\1{2,3}(.)/" "^(a)\\1{2,3}(.)" nil nil nil nil "aaaaaab" nil 1 0 "aaaaa" ("a" "a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(281 "\"the abc\" =~ /(?!^)abc/" "(?!^)abc" nil nil nil nil "the abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(282 "\"abc\" =~ /(?!^)abc/" "(?!^)abc" nil nil nil nil "abc" nil 1 0 nil nil) +(283 "\"abc\" =~ /(?=^)abc/" "(?=^)abc" nil nil nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(284 "\"the abc\" =~ /(?=^)abc/" "(?=^)abc" nil nil nil nil "the abc" nil 1 0 nil nil) +(285 "\"aabbbbb\" =~ /^[ab]{1,3}(ab*|b)/" "^[ab]{1,3}(ab*|b)" nil nil nil nil "aabbbbb" nil 1 0 "aabb" ("b" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(286 "\"aabbbbb\" =~ /^[ab]{1,3}?(ab*|b)/" "^[ab]{1,3}?(ab*|b)" nil nil nil nil "aabbbbb" nil 1 0 "aabbbbb" ("abbbbb" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(287 "\"aabbbbb\" =~ /^[ab]{1,3}?(ab*?|b)/" "^[ab]{1,3}?(ab*?|b)" nil nil nil nil "aabbbbb" nil 1 0 "aa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(288 "\"aabbbbb\" =~ /^[ab]{1,3}(ab*?|b)/" "^[ab]{1,3}(ab*?|b)" nil nil nil nil "aabbbbb" nil 1 0 "aabb" ("b" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(289 "\"Alan Other \" =~ / (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +/x" " (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +" nil nil nil t "Alan Other " nil 1 0 "Alan Other " (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(290 "\"\" =~ / (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +/x" " (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +" nil nil nil t "" nil 1 0 "user@dom.ain" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(291 "\"user\\@dom.ain\" =~ / (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +/x" " (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +" nil nil nil t "user@dom.ain" nil 1 0 "user@dom.ain" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(292 "\"\\\"A. Other\\\" (a comment)\" =~ / (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +/x" " (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +" nil nil nil t "\"A. Other\" (a comment)" nil 1 0 "\"A. Other\" (a comment)" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(293 "\"A. Other (a comment)\" =~ / (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +/x" " (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +" nil nil nil t "A. Other (a comment)" nil 1 0 " Other (a comment)" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(294 "\"\\\"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\\\"\\@x400-re.lay\" =~ / (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +/x" " (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +" nil nil nil t "\"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"@x400-re.lay" nil 1 0 "\"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"@x400-re.lay" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(295 "\"A missing angle @,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +/x" " (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +" nil nil nil t "A missing angle @,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +/x" " (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional leading comment +(?: (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] | # atom and space parts, or... +\\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) | # comments, or... + +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +# quoted strings +)* +< (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # leading < +(?: @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* + +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* , (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* )? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) # initial word +(?: (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\" (?: # opening quote... +[^\\\\\\x80-\\xff\\n\\015\"] # Anything except backslash and quote +| # or +\\\\ [^\\x80-\\xff] # Escaped something (something != CR) +)* \" # closing quote +) )* # further okay, if led by a period +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* @ (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # initial subdomain +(?: # +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* \\. # if led by a period... +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* (?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| \\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) # ...further okay +)* +# address spec +(?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* > # trailing > +# name and address +) (?: [\\040\\t] | \\( +(?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] | \\( (?: [^\\\\\\x80-\\xff\\n\\015()] | \\\\ [^\\x80-\\xff] )* \\) )* +\\) )* # optional trailing comment +" nil nil nil t "The quick brown fox" nil 1 0 nil nil) +(297 "\"Alan Other \" =~ /[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +/x" "[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +" nil nil nil t "Alan Other " nil 1 0 "Alan Other " (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(298 "\"\" =~ /[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +/x" "[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +" nil nil nil t "" nil 1 0 "user@dom.ain" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(299 "\"user\\@dom.ain\" =~ /[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +/x" "[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +" nil nil nil t "user@dom.ain" nil 1 0 "user@dom.ain" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(300 "\"\\\"A. Other\\\" (a comment)\" =~ /[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +/x" "[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +" nil nil nil t "\"A. Other\" (a comment)" nil 1 0 "\"A. Other\" " (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(301 "\"A. Other (a comment)\" =~ /[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +/x" "[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +" nil nil nil t "A. Other (a comment)" nil 1 0 " Other " (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(302 "\"\\\"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\\\"\\@x400-re.lay\" =~ /[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +/x" "[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +" nil nil nil t "\"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"@x400-re.lay" nil 1 0 "\"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"@x400-re.lay" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(303 "\"A missing angle @,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +/x" "[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +" nil nil nil t "A missing angle @,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +/x" "[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional leading comment +(?: +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +# leading word +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # \"normal\" atoms and or spaces +(?: +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +| +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +) # \"special\" comment or quoted string +[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037] * # more \"normal\" +)* +< +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +\" # \" +[^\\\\\\x80-\\xff\\n\\015\"] * # normal +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015\"] * )* # ( special normal* )* +\" # \" +# Quoted string +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\\. +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +(?: +[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+ # some number of atom characters... +(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]) # ..not followed by something that could be part of an atom +| +\\[ # [ +(?: [^\\\\\\x80-\\xff\\n\\015\\[\\]] | \\\\ [^\\x80-\\xff] )* # stuff +\\] # ] +) +[\\040\\t]* # Nab whitespace. +(?: +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: # ( +(?: \\\\ [^\\x80-\\xff] | +\\( # ( +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +(?: \\\\ [^\\x80-\\xff] [^\\\\\\x80-\\xff\\n\\015()] * )* # (special normal*)* +\\) # ) +) # special +[^\\\\\\x80-\\xff\\n\\015()] * # normal* +)* # )* +\\) # ) +[\\040\\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +" nil nil nil t "The quick brown fox" nil 1 0 nil nil) +(305 "\"abc\\0def\\00pqr\\000xyz\\0000AB\" =~ /abc\\0def\\00pqr\\000xyz\\0000AB/" "abc\\0def\\00pqr\\000xyz\\0000AB" nil nil nil nil ("abc" 0 "def" 0 "pqr" 0 "xyz" 0 "0AB") nil 1 0 ("abc" 0 "def" 0 "pqr" 0 "xyz" 0 "0AB") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(306 "\"abc456 abc\\0def\\00pqr\\000xyz\\0000ABCDE\" =~ /abc\\0def\\00pqr\\000xyz\\0000AB/" "abc\\0def\\00pqr\\000xyz\\0000AB" nil nil nil nil ("abc456 abc" 0 "def" 0 "pqr" 0 "xyz" 0 "0ABCDE") nil 1 0 ("abc" 0 "def" 0 "pqr" 0 "xyz" 0 "0AB") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(307 "\"abc\\x0def\\x00pqr\\x000xyz\\x0000AB\" =~ /abc\\x0def\\x00pqr\\x000xyz\\x0000AB/" "abc\\x0def\\x00pqr\\x000xyz\\x0000AB" nil nil nil nil ("abc" 13 "ef" 0 "pqr" 0 "0xyz" 0 "00AB") nil 1 0 ("abc" 13 "ef" 0 "pqr" 0 "0xyz" 0 "00AB") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(308 "\"abc456 abc\\x0def\\x00pqr\\x000xyz\\x0000ABCDE\" =~ /abc\\x0def\\x00pqr\\x000xyz\\x0000AB/" "abc\\x0def\\x00pqr\\x000xyz\\x0000AB" nil nil nil nil ("abc456 abc" 13 "ef" 0 "pqr" 0 "0xyz" 0 "00ABCDE") nil 1 0 ("abc" 13 "ef" 0 "pqr" 0 "0xyz" 0 "00AB") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(309 "\"\\0A\" =~ /^[\\000-\\037]/" "^[\\000-\\037]" nil nil nil nil ("" 0 "A") nil 1 0 ("" 0) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(310 "\"\\01B\" =~ /^[\\000-\\037]/" "^[\\000-\\037]" nil nil nil nil ("" 1 "B") nil 1 0 ("" 1) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(311 "\"\\037C\" =~ /^[\\000-\\037]/" "^[\\000-\\037]" nil nil nil nil ("" 31 "C") nil 1 0 ("" 31) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(312 "\"\\0\\0\\0\\0\" =~ /\\0*/" "\\0*" nil nil nil nil ("" 0 0 0 0) nil 1 0 ("" 0 0 0 0) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(313 "\"The A\\x0\\x0Z\" =~ /A\\x0{2,3}Z/" "A\\x0{2,3}Z" nil nil nil nil ("The A" 0 0 "Z") nil 1 0 ("A" 0 0 "Z") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(314 "\"An A\\0\\x0\\0Z\" =~ /A\\x0{2,3}Z/" "A\\x0{2,3}Z" nil nil nil nil ("An A" 0 0 0 "Z") nil 1 0 ("A" 0 0 0 "Z") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(315 "\"A\\0Z\" =~ /A\\x0{2,3}Z/" "A\\x0{2,3}Z" nil nil nil nil ("A" 0 "Z") nil 1 0 nil nil) +(316 "\"A\\0\\x0\\0\\x0Z\" =~ /A\\x0{2,3}Z/" "A\\x0{2,3}Z" nil nil nil nil ("A" 0 0 0 0 "Z") nil 1 0 nil nil) +(317 "\"cowcowbell\" =~ /^(cow|)\\1(bell)/" "^(cow|)\\1(bell)" nil nil nil nil "cowcowbell" nil 1 0 "cowcowbell" ("cow" "bell" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(318 "\"bell\" =~ /^(cow|)\\1(bell)/" "^(cow|)\\1(bell)" nil nil nil nil "bell" nil 1 0 "bell" ("" "bell" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(319 "\"cowbell\" =~ /^(cow|)\\1(bell)/" "^(cow|)\\1(bell)" nil nil nil nil "cowbell" nil 1 0 nil nil) +(320 "\"\\040abc\" =~ /^\\s/" "^\\s" nil nil nil nil " abc" nil 1 0 " " (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(321 "\"\\x0cabc\" =~ /^\\s/" "^\\s" nil nil nil nil ("" 12 "abc") nil 1 0 ("" 12) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(322 "\"\\nabc\" =~ /^\\s/" "^\\s" nil nil nil nil " +abc" nil 1 0 " +" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(323 "\"\\rabc\" =~ /^\\s/" "^\\s" nil nil nil nil ("" 13 "abc") nil 1 0 ("" 13) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(324 "\"\\tabc\" =~ /^\\s/" "^\\s" nil nil nil nil ("" 9 "abc") nil 1 0 ("" 9) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(325 "\"abc\" =~ /^\\s/" "^\\s" nil nil nil nil "abc" nil 1 0 nil nil) +(326 ("\"abc\" =~ /^a" 9 "b" 10 " " 13 " " 12 " c/x") "^a b + c" nil nil nil t "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(327 "\"ab\" =~ /^(a|)\\1*b/" "^(a|)\\1*b" nil nil nil nil "ab" nil 1 0 "ab" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(328 "\"aaaab\" =~ /^(a|)\\1*b/" "^(a|)\\1*b" nil nil nil nil "aaaab" nil 1 0 "aaaab" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(329 "\"b\" =~ /^(a|)\\1*b/" "^(a|)\\1*b" nil nil nil nil "b" nil 1 0 "b" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(330 "\"acb\" =~ /^(a|)\\1*b/" "^(a|)\\1*b" nil nil nil nil "acb" nil 1 0 nil nil) +(331 "\"aab\" =~ /^(a|)\\1+b/" "^(a|)\\1+b" nil nil nil nil "aab" nil 1 0 "aab" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(332 "\"aaaab\" =~ /^(a|)\\1+b/" "^(a|)\\1+b" nil nil nil nil "aaaab" nil 1 0 "aaaab" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(333 "\"b\" =~ /^(a|)\\1+b/" "^(a|)\\1+b" nil nil nil nil "b" nil 1 0 "b" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(334 "\"ab\" =~ /^(a|)\\1+b/" "^(a|)\\1+b" nil nil nil nil "ab" nil 1 0 nil nil) +(335 "\"ab\" =~ /^(a|)\\1?b/" "^(a|)\\1?b" nil nil nil nil "ab" nil 1 0 "ab" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(336 "\"aab\" =~ /^(a|)\\1?b/" "^(a|)\\1?b" nil nil nil nil "aab" nil 1 0 "aab" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(337 "\"b\" =~ /^(a|)\\1?b/" "^(a|)\\1?b" nil nil nil nil "b" nil 1 0 "b" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(338 "\"acb\" =~ /^(a|)\\1?b/" "^(a|)\\1?b" nil nil nil nil "acb" nil 1 0 nil nil) +(339 "\"aaab\" =~ /^(a|)\\1{2}b/" "^(a|)\\1{2}b" nil nil nil nil "aaab" nil 1 0 "aaab" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(340 "\"b\" =~ /^(a|)\\1{2}b/" "^(a|)\\1{2}b" nil nil nil nil "b" nil 1 0 "b" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(341 "\"ab\" =~ /^(a|)\\1{2}b/" "^(a|)\\1{2}b" nil nil nil nil "ab" nil 1 0 nil nil) +(342 "\"aab\" =~ /^(a|)\\1{2}b/" "^(a|)\\1{2}b" nil nil nil nil "aab" nil 1 0 nil nil) +(343 "\"aaaab\" =~ /^(a|)\\1{2}b/" "^(a|)\\1{2}b" nil nil nil nil "aaaab" nil 1 0 nil nil) +(344 "\"aaab\" =~ /^(a|)\\1{2,3}b/" "^(a|)\\1{2,3}b" nil nil nil nil "aaab" nil 1 0 "aaab" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(345 "\"aaaab\" =~ /^(a|)\\1{2,3}b/" "^(a|)\\1{2,3}b" nil nil nil nil "aaaab" nil 1 0 "aaaab" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(346 "\"b\" =~ /^(a|)\\1{2,3}b/" "^(a|)\\1{2,3}b" nil nil nil nil "b" nil 1 0 "b" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(347 "\"ab\" =~ /^(a|)\\1{2,3}b/" "^(a|)\\1{2,3}b" nil nil nil nil "ab" nil 1 0 nil nil) +(348 "\"aab\" =~ /^(a|)\\1{2,3}b/" "^(a|)\\1{2,3}b" nil nil nil nil "aab" nil 1 0 nil nil) +(349 "\"aaaaab\" =~ /^(a|)\\1{2,3}b/" "^(a|)\\1{2,3}b" nil nil nil nil "aaaaab" nil 1 0 nil nil) +(350 "\"abbbbc\" =~ /ab{1,3}bc/" "ab{1,3}bc" nil nil nil nil "abbbbc" nil 1 0 "abbbbc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(351 "\"abbbc\" =~ /ab{1,3}bc/" "ab{1,3}bc" nil nil nil nil "abbbc" nil 1 0 "abbbc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(352 "\"abbc\" =~ /ab{1,3}bc/" "ab{1,3}bc" nil nil nil nil "abbc" nil 1 0 "abbc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(353 "\"abc\" =~ /ab{1,3}bc/" "ab{1,3}bc" nil nil nil nil "abc" nil 1 0 nil nil) +(354 "\"abbbbbc\" =~ /ab{1,3}bc/" "ab{1,3}bc" nil nil nil nil "abbbbbc" nil 1 0 nil nil) +(355 "\"track1.title:TBlah blah blah\" =~ /([^.]*)\\.([^:]*):[T ]+(.*)/" "([^.]*)\\.([^:]*):[T ]+(.*)" nil nil nil nil "track1.title:TBlah blah blah" nil 1 0 "track1.title:TBlah blah blah" ("track1" "title" "Blah blah blah" nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(356 "\"track1.title:TBlah blah blah\" =~ /([^.]*)\\.([^:]*):[T ]+(.*)/i" "([^.]*)\\.([^:]*):[T ]+(.*)" t nil nil nil "track1.title:TBlah blah blah" nil 1 0 "track1.title:TBlah blah blah" ("track1" "title" "Blah blah blah" nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(357 "\"track1.title:TBlah blah blah\" =~ /([^.]*)\\.([^:]*):[t ]+(.*)/i" "([^.]*)\\.([^:]*):[t ]+(.*)" t nil nil nil "track1.title:TBlah blah blah" nil 1 0 "track1.title:TBlah blah blah" ("track1" "title" "Blah blah blah" nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(358 "\"WXY_^abc\" =~ /^[W-c]+$/" "^[W-c]+$" nil nil nil nil "WXY_^abc" nil 1 0 "WXY_^abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(359 "\"wxy\" =~ /^[W-c]+$/" "^[W-c]+$" nil nil nil nil "wxy" nil 1 0 nil nil) +(360 "\"WXY_^abc\" =~ /^[W-c]+$/i" "^[W-c]+$" t nil nil nil "WXY_^abc" nil 1 0 "WXY_^abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(361 "\"wxy_^ABC\" =~ /^[W-c]+$/i" "^[W-c]+$" t nil nil nil "wxy_^ABC" nil 1 0 "wxy_^ABC" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(362 "\"WXY_^abc\" =~ /^[\\x3f-\\x5F]+$/i" "^[\\x3f-\\x5F]+$" t nil nil nil "WXY_^abc" nil 1 0 "WXY_^abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(363 "\"wxy_^ABC\" =~ /^[\\x3f-\\x5F]+$/i" "^[\\x3f-\\x5F]+$" t nil nil nil "wxy_^ABC" nil 1 0 "wxy_^ABC" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(364 "\"abc\" =~ /^abc$/m" "^abc$" nil t nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(365 "\"qqq\\nabc\" =~ /^abc$/m" "^abc$" nil t nil nil "qqq +abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(366 "\"abc\\nzzz\" =~ /^abc$/m" "^abc$" nil t nil nil "abc +zzz" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(367 "\"qqq\\nabc\\nzzz\" =~ /^abc$/m" "^abc$" nil t nil nil "qqq +abc +zzz" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(368 "\"abc\" =~ /^abc$/" "^abc$" nil nil nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(369 "\"qqq\\nabc\" =~ /^abc$/" "^abc$" nil nil nil nil "qqq +abc" nil 1 0 nil nil) +(370 "\"abc\\nzzz\" =~ /^abc$/" "^abc$" nil nil nil nil "abc +zzz" nil 1 0 nil nil) +(371 "\"qqq\\nabc\\nzzz\" =~ /^abc$/" "^abc$" nil nil nil nil "qqq +abc +zzz" nil 1 0 nil nil) +(372 "\"abc\" =~ /\\Aabc\\Z/m" "\\Aabc\\Z" nil t nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(373 "\"abc\\n\" =~ /\\Aabc\\Z/m" "\\Aabc\\Z" nil t nil nil "abc +" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(374 "\"qqq\\nabc\" =~ /\\Aabc\\Z/m" "\\Aabc\\Z" nil t nil nil "qqq +abc" nil 1 0 nil nil) +(375 "\"abc\\nzzz\" =~ /\\Aabc\\Z/m" "\\Aabc\\Z" nil t nil nil "abc +zzz" nil 1 0 nil nil) +(376 "\"qqq\\nabc\\nzzz\" =~ /\\Aabc\\Z/m" "\\Aabc\\Z" nil t nil nil "qqq +abc +zzz" nil 1 0 nil nil) +(377 "\"abc\\ndef\" =~ /\\A(.)*\\Z/s" "\\A(.)*\\Z" nil nil t nil "abc +def" nil 1 0 "abc +def" ("f" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(378 "\"abc\\ndef\" =~ /\\A(.)*\\Z/m" "\\A(.)*\\Z" nil t nil nil "abc +def" nil 1 0 nil nil) +(379 "\"b::c\" =~ /(?:b)|(?::+)/" "(?:b)|(?::+)" nil nil nil nil "b::c" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(380 "\"c::b\" =~ /(?:b)|(?::+)/" "(?:b)|(?::+)" nil nil nil nil "c::b" nil 1 0 "::" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(381 "\"az-\" =~ /[-az]+/" "[-az]+" nil nil nil nil "az-" nil 1 0 "az-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(382 "\"b\" =~ /[-az]+/" "[-az]+" nil nil nil nil "b" nil 1 0 nil nil) +(383 "\"za-\" =~ /[az-]+/" "[az-]+" nil nil nil nil "za-" nil 1 0 "za-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(384 "\"b\" =~ /[az-]+/" "[az-]+" nil nil nil nil "b" nil 1 0 nil nil) +(385 "\"a-z\" =~ /[a\\-z]+/" "[a\\-z]+" nil nil nil nil "a-z" nil 1 0 "a-z" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(386 "\"b\" =~ /[a\\-z]+/" "[a\\-z]+" nil nil nil nil "b" nil 1 0 nil nil) +(387 "\"abcdxyz\" =~ /[a-z]+/" "[a-z]+" nil nil nil nil "abcdxyz" nil 1 0 "abcdxyz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(388 "\"12-34\" =~ /[\\d-]+/" "[\\d-]+" nil nil nil nil "12-34" nil 1 0 "12-34" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(389 "\"aaa\" =~ /[\\d-]+/" "[\\d-]+" nil nil nil nil "aaa" nil 1 0 nil nil) +(390 "\"12-34z\" =~ /[\\d-z]+/" "[\\d-z]+" nil nil nil nil "12-34z" nil 1 0 "12-34z" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(391 "\"aaa\" =~ /[\\d-z]+/" "[\\d-z]+" nil nil nil nil "aaa" nil 1 0 nil nil) +(392 "\"\\\\\" =~ /\\x5c/" "\\x5c" nil nil nil nil "\\" nil 1 0 "\\" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(393 "\"the Zoo\" =~ /\\x20Z/" "\\x20Z" nil nil nil nil "the Zoo" nil 1 0 " Z" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(394 "\"Zulu\" =~ /\\x20Z/" "\\x20Z" nil nil nil nil "Zulu" nil 1 0 nil nil) +(395 "\"abcabc\" =~ /(abc)\\1/i" "(abc)\\1" t nil nil nil "abcabc" nil 1 0 "abcabc" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(396 "\"ABCabc\" =~ /(abc)\\1/i" "(abc)\\1" t nil nil nil "ABCabc" nil 1 0 "ABCabc" ("ABC" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(397 "\"abcABC\" =~ /(abc)\\1/i" "(abc)\\1" t nil nil nil "abcABC" nil 1 0 "abcABC" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(398 "\"ab{3cd\" =~ /ab{3cd/" "ab{3cd" nil nil nil nil "ab{3cd" nil 1 0 "ab{3cd" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(399 "\"ab{3,cd\" =~ /ab{3,cd/" "ab{3,cd" nil nil nil nil "ab{3,cd" nil 1 0 "ab{3,cd" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(400 "\"ab{3,4a}cd\" =~ /ab{3,4a}cd/" "ab{3,4a}cd" nil nil nil nil "ab{3,4a}cd" nil 1 0 "ab{3,4a}cd" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(401 "\"{4,5a}bc\" =~ /{4,5a}bc/" "{4,5a}bc" nil nil nil nil "{4,5a}bc" nil 1 0 "{4,5a}bc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(402 "\"a\\rb\" =~ /^a.b/" "^a.b" nil nil nil nil ("a" 13 "b") nil 1 0 ("a" 13 "b") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(403 "\"a\\nb\" =~ /^a.b/" "^a.b" nil nil nil nil "a +b" nil 1 0 nil nil) +(404 "\"abc\" =~ /abc$/" "abc$" nil nil nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(405 "\"abc\\n\" =~ /abc$/" "abc$" nil nil nil nil "abc +" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(406 "\"abc\\ndef\" =~ /abc$/" "abc$" nil nil nil nil "abc +def" nil 1 0 nil nil) +(407 "\"abc\\x53\" =~ /(abc)\\123/" "(abc)\\123" nil nil nil nil "abcS" nil 1 0 "abcS" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(408 "\"abc\\x93\" =~ /(abc)\\223/" "(abc)\\223" nil nil nil nil ("abc" 147) nil 1 0 ("abc" 147) ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(409 "\"abc\\xd3\" =~ /(abc)\\323/" "(abc)\\323" nil nil nil nil ("abc" 211) nil 1 0 ("abc" 211) ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(410 "\"abc\\x40\" =~ /(abc)\\500/" "(abc)\\500" nil nil nil nil "abc@" nil 1 0 "abc@" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(411 "\"abc\\100\" =~ /(abc)\\500/" "(abc)\\500" nil nil nil nil "abc@" nil 1 0 "abc@" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(412 "\"abc\\x400\" =~ /(abc)\\5000/" "(abc)\\5000" nil nil nil nil "abc@0" nil 1 0 "abc@0" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(413 "\"abc\\x40\\x30\" =~ /(abc)\\5000/" "(abc)\\5000" nil nil nil nil "abc@0" nil 1 0 "abc@0" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(414 "\"abc\\1000\" =~ /(abc)\\5000/" "(abc)\\5000" nil nil nil nil "abc@0" nil 1 0 "abc@0" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(415 "\"abc\\100\\x30\" =~ /(abc)\\5000/" "(abc)\\5000" nil nil nil nil "abc@0" nil 1 0 "abc@0" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(416 "\"abc\\100\\060\" =~ /(abc)\\5000/" "(abc)\\5000" nil nil nil nil "abc@0" nil 1 0 "abc@0" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(417 "\"abc\\100\\60\" =~ /(abc)\\5000/" "(abc)\\5000" nil nil nil nil "abc@0" nil 1 0 "abc@0" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(418 "\"abc\\081\" =~ /abc\\81/" "abc\\81" nil nil nil nil ("abc" 0 "81") nil 1 0 ("abc" 0 "81") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(419 "\"abc\\0\\x38\\x31\" =~ /abc\\81/" "abc\\81" nil nil nil nil ("abc" 0 "81") nil 1 0 ("abc" 0 "81") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(420 "\"abc\\091\" =~ /abc\\91/" "abc\\91" nil nil nil nil ("abc" 0 "91") nil 1 0 ("abc" 0 "91") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(421 "\"abc\\0\\x39\\x31\" =~ /abc\\91/" "abc\\91" nil nil nil nil ("abc" 0 "91") nil 1 0 ("abc" 0 "91") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(422 "\"abcdefghijkllS\" =~ /(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\\12\\123/" "(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\\12\\123" nil nil nil nil "abcdefghijkllS" nil 1 0 "abcdefghijkllS" ("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" nil nil nil nil)) +(423 "\"abcdefghijk\\12S\" =~ /(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\12\\123/" "(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\12\\123" nil nil nil nil "abcdefghijk +S" nil 1 0 "abcdefghijk +S" ("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" nil nil nil nil nil)) +(424 "\"abgdef\" =~ /ab\\gdef/" "ab\\gdef" nil nil nil nil "abgdef" nil 1 0 "abgdef" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(425 "\"bc\" =~ /a{0}bc/" "a{0}bc" nil nil nil nil "bc" nil 1 0 "bc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(426 "\"xyz\" =~ /(a|(bc)){0,0}?xyz/" "(a|(bc)){0,0}?xyz" nil nil nil nil "xyz" nil 1 0 "xyz" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(427 "\"abc\\010de\" =~ /abc[\\10]de/" "abc[\\10]de" nil nil nil nil ("abc" 8 "de") nil 1 0 ("abc" 8 "de") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(428 "\"abc\\1de\" =~ /abc[\\1]de/" "abc[\\1]de" nil nil nil nil ("abc" 1 "de") nil 1 0 ("abc" 1 "de") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(429 "\"abc\\1de\" =~ /(abc)[\\1]de/" "(abc)[\\1]de" nil nil nil nil ("abc" 1 "de") nil 1 0 ("abc" 1 "de") ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(430 "\"a\\nb\" =~ /a.b(?s)/" "a.b(?s)" nil nil nil nil "a +b" nil 1 0 nil nil) +(431 "\"baNOTccccd\" =~ /^([^a])([^\\b])([^c]*)([^d]{3,4})/" "^([^a])([^\\b])([^c]*)([^d]{3,4})" nil nil nil nil "baNOTccccd" nil 1 0 "baNOTcccc" ("b" "a" "NOT" "cccc" nil nil nil nil nil nil nil nil nil nil nil nil)) +(432 "\"baNOTcccd\" =~ /^([^a])([^\\b])([^c]*)([^d]{3,4})/" "^([^a])([^\\b])([^c]*)([^d]{3,4})" nil nil nil nil "baNOTcccd" nil 1 0 "baNOTccc" ("b" "a" "NOT" "ccc" nil nil nil nil nil nil nil nil nil nil nil nil)) +(433 "\"baNOTccd\" =~ /^([^a])([^\\b])([^c]*)([^d]{3,4})/" "^([^a])([^\\b])([^c]*)([^d]{3,4})" nil nil nil nil "baNOTccd" nil 1 0 "baNOTcc" ("b" "a" "NO" "Tcc" nil nil nil nil nil nil nil nil nil nil nil nil)) +(434 "\"bacccd\" =~ /^([^a])([^\\b])([^c]*)([^d]{3,4})/" "^([^a])([^\\b])([^c]*)([^d]{3,4})" nil nil nil nil "bacccd" nil 1 0 "baccc" ("b" "a" "" "ccc" nil nil nil nil nil nil nil nil nil nil nil nil)) +(435 "\"anything\" =~ /^([^a])([^\\b])([^c]*)([^d]{3,4})/" "^([^a])([^\\b])([^c]*)([^d]{3,4})" nil nil nil nil "anything" nil 1 0 nil nil) +(436 "\"b\\bc\" =~ /^([^a])([^\\b])([^c]*)([^d]{3,4})/" "^([^a])([^\\b])([^c]*)([^d]{3,4})" nil nil nil nil ("b" 8 "c") nil 1 0 nil nil) +(437 "\"baccd\" =~ /^([^a])([^\\b])([^c]*)([^d]{3,4})/" "^([^a])([^\\b])([^c]*)([^d]{3,4})" nil nil nil nil "baccd" nil 1 0 nil nil) +(438 "\"Abc\" =~ /[^a]/" "[^a]" nil nil nil nil "Abc" nil 1 0 "A" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(439 "\"Abc\" =~ /[^a]/i" "[^a]" t nil nil nil "Abc" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(440 "\"AAAaAbc\" =~ /[^a]+/" "[^a]+" nil nil nil nil "AAAaAbc" nil 1 0 "AAA" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(441 "\"AAAaAbc\" =~ /[^a]+/i" "[^a]+" t nil nil nil "AAAaAbc" nil 1 0 "bc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(442 "\"bbb\\nccc\" =~ /[^a]+/" "[^a]+" nil nil nil nil "bbb +ccc" nil 1 0 "bbb +ccc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(443 "\"abc\" =~ /[^k]$/" "[^k]$" nil nil nil nil "abc" nil 1 0 "c" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(444 "\"abk\" =~ /[^k]$/" "[^k]$" nil nil nil nil "abk" nil 1 0 nil nil) +(445 "\"abc\" =~ /[^k]{2,3}$/" "[^k]{2,3}$" nil nil nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(446 "\"kbc\" =~ /[^k]{2,3}$/" "[^k]{2,3}$" nil nil nil nil "kbc" nil 1 0 "bc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(447 "\"kabc\" =~ /[^k]{2,3}$/" "[^k]{2,3}$" nil nil nil nil "kabc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(448 "\"abk\" =~ /[^k]{2,3}$/" "[^k]{2,3}$" nil nil nil nil "abk" nil 1 0 nil nil) +(449 "\"akb\" =~ /[^k]{2,3}$/" "[^k]{2,3}$" nil nil nil nil "akb" nil 1 0 nil nil) +(450 "\"akk\" =~ /[^k]{2,3}$/" "[^k]{2,3}$" nil nil nil nil "akk" nil 1 0 nil nil) +(451 "\"12345678\\@a.b.c.d\" =~ /^\\d{8,}\\@.+[^k]$/" "^\\d{8,}\\@.+[^k]$" nil nil nil nil "12345678@a.b.c.d" nil 1 0 "12345678@a.b.c.d" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(452 "\"123456789\\@x.y.z\" =~ /^\\d{8,}\\@.+[^k]$/" "^\\d{8,}\\@.+[^k]$" nil nil nil nil "123456789@x.y.z" nil 1 0 "123456789@x.y.z" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(453 "\"12345678\\@x.y.uk\" =~ /^\\d{8,}\\@.+[^k]$/" "^\\d{8,}\\@.+[^k]$" nil nil nil nil "12345678@x.y.uk" nil 1 0 nil nil) +(454 "\"1234567\\@a.b.c.d\" =~ /^\\d{8,}\\@.+[^k]$/" "^\\d{8,}\\@.+[^k]$" nil nil nil nil "1234567@a.b.c.d" nil 1 0 nil nil) +(455 "\"aaaaaaaaa\" =~ /(a)\\1{8,}/" "(a)\\1{8,}" nil nil nil nil "aaaaaaaaa" nil 1 0 "aaaaaaaaa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(456 "\"aaaaaaaaaa\" =~ /(a)\\1{8,}/" "(a)\\1{8,}" nil nil nil nil "aaaaaaaaaa" nil 1 0 "aaaaaaaaaa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(457 "\"aaaaaaa\" =~ /(a)\\1{8,}/" "(a)\\1{8,}" nil nil nil nil "aaaaaaa" nil 1 0 nil nil) +(458 "\"aaaabcd\" =~ /[^a]/" "[^a]" nil nil nil nil "aaaabcd" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(459 "\"aaAabcd\" =~ /[^a]/" "[^a]" nil nil nil nil "aaAabcd" nil 1 0 "A" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(460 "\"aaaabcd\" =~ /[^a]/i" "[^a]" t nil nil nil "aaaabcd" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(461 "\"aaAabcd\" =~ /[^a]/i" "[^a]" t nil nil nil "aaAabcd" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(462 "\"aaaabcd\" =~ /[^az]/" "[^az]" nil nil nil nil "aaaabcd" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(463 "\"aaAabcd\" =~ /[^az]/" "[^az]" nil nil nil nil "aaAabcd" nil 1 0 "A" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(464 "\"aaaabcd\" =~ /[^az]/i" "[^az]" t nil nil nil "aaaabcd" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(465 "\"aaAabcd\" =~ /[^az]/i" "[^az]" t nil nil nil "aaAabcd" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(466 "\"\\000\\001\\002\\003\\004\\005\\006\\007\\010\\011\\012\\013\\014\\015\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\\040\\041\\042\\043\\044\\045\\046\\047\\050\\051\\052\\053\\054\\055\\056\\057\\060\\061\\062\\063\\064\\065\\066\\067\\070\\071\\072\\073\\074\\075\\076\\077\\100\\101\\102\\103\\104\\105\\106\\107\\110\\111\\112\\113\\114\\115\\116\\117\\120\\121\\122\\123\\124\\125\\126\\127\\130\\131\\132\\133\\134\\135\\136\\137\\140\\141\\142\\143\\144\\145\\146\\147\\150\\151\\152\\153\\154\\155\\156\\157\\160\\161\\162\\163\\164\\165\\166\\167\\170\\171\\172\\173\\174\\175\\176\\177\\200\\201\\202\\203\\204\\205\\206\\207\\210\\211\\212\\213\\214\\215\\216\\217\\220\\221\\222\\223\\224\\225\\226\\227\\230\\231\\232\\233\\234\\235\\236\\237\\240\\241\\242\\243\\244\\245\\246\\247\\250\\251\\252\\253\\254\\255\\256\\257\\260\\261\\262\\263\\264\\265\\266\\267\\270\\271\\272\\273\\274\\275\\276\\277\\300\\301\\302\\303\\304\\305\\306\\307\\310\\311\\312\\313\\314\\315\\316\\317\\320\\321\\322\\323\\324\\325\\326\\327\\330\\331\\332\\333\\334\\335\\336\\337\\340\\341\\342\\343\\344\\345\\346\\347\\350\\351\\352\\353\\354\\355\\356\\357\\360\\361\\362\\363\\364\\365\\366\\367\\370\\371\\372\\373\\374\\375\\376\\377\" =~ /\\000\\001\\002\\003\\004\\005\\006\\007\\010\\011\\012\\013\\014\\015\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\\040\\041\\042\\043\\044\\045\\046\\047\\050\\051\\052\\053\\054\\055\\056\\057\\060\\061\\062\\063\\064\\065\\066\\067\\070\\071\\072\\073\\074\\075\\076\\077\\100\\101\\102\\103\\104\\105\\106\\107\\110\\111\\112\\113\\114\\115\\116\\117\\120\\121\\122\\123\\124\\125\\126\\127\\130\\131\\132\\133\\134\\135\\136\\137\\140\\141\\142\\143\\144\\145\\146\\147\\150\\151\\152\\153\\154\\155\\156\\157\\160\\161\\162\\163\\164\\165\\166\\167\\170\\171\\172\\173\\174\\175\\176\\177\\200\\201\\202\\203\\204\\205\\206\\207\\210\\211\\212\\213\\214\\215\\216\\217\\220\\221\\222\\223\\224\\225\\226\\227\\230\\231\\232\\233\\234\\235\\236\\237\\240\\241\\242\\243\\244\\245\\246\\247\\250\\251\\252\\253\\254\\255\\256\\257\\260\\261\\262\\263\\264\\265\\266\\267\\270\\271\\272\\273\\274\\275\\276\\277\\300\\301\\302\\303\\304\\305\\306\\307\\310\\311\\312\\313\\314\\315\\316\\317\\320\\321\\322\\323\\324\\325\\326\\327\\330\\331\\332\\333\\334\\335\\336\\337\\340\\341\\342\\343\\344\\345\\346\\347\\350\\351\\352\\353\\354\\355\\356\\357\\360\\361\\362\\363\\364\\365\\366\\367\\370\\371\\372\\373\\374\\375\\376\\377/" "\\000\\001\\002\\003\\004\\005\\006\\007\\010\\011\\012\\013\\014\\015\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\\040\\041\\042\\043\\044\\045\\046\\047\\050\\051\\052\\053\\054\\055\\056\\057\\060\\061\\062\\063\\064\\065\\066\\067\\070\\071\\072\\073\\074\\075\\076\\077\\100\\101\\102\\103\\104\\105\\106\\107\\110\\111\\112\\113\\114\\115\\116\\117\\120\\121\\122\\123\\124\\125\\126\\127\\130\\131\\132\\133\\134\\135\\136\\137\\140\\141\\142\\143\\144\\145\\146\\147\\150\\151\\152\\153\\154\\155\\156\\157\\160\\161\\162\\163\\164\\165\\166\\167\\170\\171\\172\\173\\174\\175\\176\\177\\200\\201\\202\\203\\204\\205\\206\\207\\210\\211\\212\\213\\214\\215\\216\\217\\220\\221\\222\\223\\224\\225\\226\\227\\230\\231\\232\\233\\234\\235\\236\\237\\240\\241\\242\\243\\244\\245\\246\\247\\250\\251\\252\\253\\254\\255\\256\\257\\260\\261\\262\\263\\264\\265\\266\\267\\270\\271\\272\\273\\274\\275\\276\\277\\300\\301\\302\\303\\304\\305\\306\\307\\310\\311\\312\\313\\314\\315\\316\\317\\320\\321\\322\\323\\324\\325\\326\\327\\330\\331\\332\\333\\334\\335\\336\\337\\340\\341\\342\\343\\344\\345\\346\\347\\350\\351\\352\\353\\354\\355\\356\\357\\360\\361\\362\\363\\364\\365\\366\\367\\370\\371\\372\\373\\374\\375\\376\\377" nil nil nil nil ("" 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255) nil 1 0 ("" 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(467 "\"xxxxxxxxxxxPSTAIREISLLxxxxxxxxx\" =~ /P[^*]TAIRE[^*]{1,6}?LL/" "P[^*]TAIRE[^*]{1,6}?LL" nil nil nil nil "xxxxxxxxxxxPSTAIREISLLxxxxxxxxx" nil 1 0 "PSTAIREISLL" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(468 "\"xxxxxxxxxxxPSTAIREISLLxxxxxxxxx\" =~ /P[^*]TAIRE[^*]{1,}?LL/" "P[^*]TAIRE[^*]{1,}?LL" nil nil nil nil "xxxxxxxxxxxPSTAIREISLLxxxxxxxxx" nil 1 0 "PSTAIREISLL" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(469 "\"1.230003938\" =~ /(\\.\\d\\d[1-9]?)\\d+/" "(\\.\\d\\d[1-9]?)\\d+" nil nil nil nil "1.230003938" nil 1 0 ".230003938" (".23" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(470 "\"1.875000282\" =~ /(\\.\\d\\d[1-9]?)\\d+/" "(\\.\\d\\d[1-9]?)\\d+" nil nil nil nil "1.875000282" nil 1 0 ".875000282" (".875" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(471 "\"1.235\" =~ /(\\.\\d\\d[1-9]?)\\d+/" "(\\.\\d\\d[1-9]?)\\d+" nil nil nil nil "1.235" nil 1 0 ".235" (".23" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(472 "\"1.230003938\" =~ /(\\.\\d\\d((?=0)|\\d(?=\\d)))/" "(\\.\\d\\d((?=0)|\\d(?=\\d)))" nil nil nil nil "1.230003938" nil 1 0 ".23" (".23" "" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(473 "\"1.875000282\" =~ /(\\.\\d\\d((?=0)|\\d(?=\\d)))/" "(\\.\\d\\d((?=0)|\\d(?=\\d)))" nil nil nil nil "1.875000282" nil 1 0 ".875" (".875" "5" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(474 "\"1.235\" =~ /(\\.\\d\\d((?=0)|\\d(?=\\d)))/" "(\\.\\d\\d((?=0)|\\d(?=\\d)))" nil nil nil nil "1.235" nil 1 0 nil nil) +(475 "\"ab\" =~ /a(?)b/" "a(?)b" nil nil nil nil "ab" nil 1 0 "ab" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(476 "\"Food is on the foo table\" =~ /\\b(foo)\\s+(\\w+)/i" "\\b(foo)\\s+(\\w+)" t nil nil nil "Food is on the foo table" nil 1 0 "foo table" ("foo" "table" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(477 "\"The food is under the bar in the barn.\" =~ /foo(.*)bar/" "foo(.*)bar" nil nil nil nil "The food is under the bar in the barn." nil 1 0 "food is under the bar in the bar" ("d is under the bar in the " nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(478 "\"The food is under the bar in the barn.\" =~ /foo(.*?)bar/" "foo(.*?)bar" nil nil nil nil "The food is under the bar in the barn." nil 1 0 "food is under the bar" ("d is under the " nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(479 "\"I have 2 numbers: 53147\" =~ /(.*)(\\d*)/" "(.*)(\\d*)" nil nil nil nil "I have 2 numbers: 53147" nil 1 0 "I have 2 numbers: 53147" ("I have 2 numbers: 53147" "" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(480 "\"I have 2 numbers: 53147\" =~ /(.*)(\\d+)/" "(.*)(\\d+)" nil nil nil nil "I have 2 numbers: 53147" nil 1 0 "I have 2 numbers: 53147" ("I have 2 numbers: 5314" "7" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(481 "\"I have 2 numbers: 53147\" =~ /(.*?)(\\d*)/" "(.*?)(\\d*)" nil nil nil nil "I have 2 numbers: 53147" nil 1 0 "" ("" "" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(482 "\"I have 2 numbers: 53147\" =~ /(.*?)(\\d+)/" "(.*?)(\\d+)" nil nil nil nil "I have 2 numbers: 53147" nil 1 0 "I have 2" ("I have " "2" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(483 "\"I have 2 numbers: 53147\" =~ /(.*)(\\d+)$/" "(.*)(\\d+)$" nil nil nil nil "I have 2 numbers: 53147" nil 1 0 "I have 2 numbers: 53147" ("I have 2 numbers: 5314" "7" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(484 "\"I have 2 numbers: 53147\" =~ /(.*?)(\\d+)$/" "(.*?)(\\d+)$" nil nil nil nil "I have 2 numbers: 53147" nil 1 0 "I have 2 numbers: 53147" ("I have 2 numbers: " "53147" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(485 "\"I have 2 numbers: 53147\" =~ /(.*)\\b(\\d+)$/" "(.*)\\b(\\d+)$" nil nil nil nil "I have 2 numbers: 53147" nil 1 0 "I have 2 numbers: 53147" ("I have 2 numbers: " "53147" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(486 "\"I have 2 numbers: 53147\" =~ /(.*\\D)(\\d+)$/" "(.*\\D)(\\d+)$" nil nil nil nil "I have 2 numbers: 53147" nil 1 0 "I have 2 numbers: 53147" ("I have 2 numbers: " "53147" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(487 "\"ABC123\" =~ /^\\D*(?!123)/" "^\\D*(?!123)" nil nil nil nil "ABC123" nil 1 0 "AB" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(488 "\"ABC445\" =~ /^(\\D*)(?=\\d)(?!123)/" "^(\\D*)(?=\\d)(?!123)" nil nil nil nil "ABC445" nil 1 0 "ABC" ("ABC" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(489 "\"ABC123\" =~ /^(\\D*)(?=\\d)(?!123)/" "^(\\D*)(?=\\d)(?!123)" nil nil nil nil "ABC123" nil 1 0 nil nil) +(490 "\"W46]789\" =~ /^[W-]46]/" "^[W-]46]" nil nil nil nil "W46]789" nil 1 0 "W46]" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(491 "\"-46]789\" =~ /^[W-]46]/" "^[W-]46]" nil nil nil nil "-46]789" nil 1 0 "-46]" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(492 "\"Wall\" =~ /^[W-]46]/" "^[W-]46]" nil nil nil nil "Wall" nil 1 0 nil nil) +(493 "\"Zebra\" =~ /^[W-]46]/" "^[W-]46]" nil nil nil nil "Zebra" nil 1 0 nil nil) +(494 "\"42\" =~ /^[W-]46]/" "^[W-]46]" nil nil nil nil "42" nil 1 0 nil nil) +(495 "\"[abcd]\" =~ /^[W-]46]/" "^[W-]46]" nil nil nil nil "[abcd]" nil 1 0 nil nil) +(496 "\"]abcd[\" =~ /^[W-]46]/" "^[W-]46]" nil nil nil nil "]abcd[" nil 1 0 nil nil) +(497 "\"W46]789\" =~ /^[W-\\]46]/" "^[W-\\]46]" nil nil nil nil "W46]789" nil 1 0 "W" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(498 "\"Wall\" =~ /^[W-\\]46]/" "^[W-\\]46]" nil nil nil nil "Wall" nil 1 0 "W" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(499 "\"Zebra\" =~ /^[W-\\]46]/" "^[W-\\]46]" nil nil nil nil "Zebra" nil 1 0 "Z" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(500 "\"Xylophone\" =~ /^[W-\\]46]/" "^[W-\\]46]" nil nil nil nil "Xylophone" nil 1 0 "X" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(501 "\"42\" =~ /^[W-\\]46]/" "^[W-\\]46]" nil nil nil nil "42" nil 1 0 "4" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(502 "\"[abcd]\" =~ /^[W-\\]46]/" "^[W-\\]46]" nil nil nil nil "[abcd]" nil 1 0 "[" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(503 "\"]abcd[\" =~ /^[W-\\]46]/" "^[W-\\]46]" nil nil nil nil "]abcd[" nil 1 0 "]" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(504 "\"\\\\backslash\" =~ /^[W-\\]46]/" "^[W-\\]46]" nil nil nil nil "\\backslash" nil 1 0 "\\" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(505 "\"-46]789\" =~ /^[W-\\]46]/" "^[W-\\]46]" nil nil nil nil "-46]789" nil 1 0 nil nil) +(506 "\"well\" =~ /^[W-\\]46]/" "^[W-\\]46]" nil nil nil nil "well" nil 1 0 nil nil) +(507 "\"01/01/2000\" =~ /\\d\\d\\/\\d\\d\\/\\d\\d\\d\\d/" "\\d\\d\\/\\d\\d\\/\\d\\d\\d\\d" nil nil nil nil "01/01/2000" nil 1 0 "01/01/2000" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(508 "\"word cat dog elephant mussel cow horse canary baboon snake shark otherword\" =~ /word (?:[a-zA-Z0-9]+ ){0,10}otherword/" "word (?:[a-zA-Z0-9]+ ){0,10}otherword" nil nil nil nil "word cat dog elephant mussel cow horse canary baboon snake shark otherword" nil 1 0 "word cat dog elephant mussel cow horse canary baboon snake shark otherword" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(509 "\"word cat dog elephant mussel cow horse canary baboon snake shark\" =~ /word (?:[a-zA-Z0-9]+ ){0,10}otherword/" "word (?:[a-zA-Z0-9]+ ){0,10}otherword" nil nil nil nil "word cat dog elephant mussel cow horse canary baboon snake shark" nil 1 0 nil nil) +(510 "\"word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope\" =~ /word (?:[a-zA-Z0-9]+ ){0,300}otherword/" "word (?:[a-zA-Z0-9]+ ){0,300}otherword" nil nil nil nil "word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope" nil 1 0 nil nil) +(511 "\"bcd\" =~ /^(a){0,0}/" "^(a){0,0}" nil nil nil nil "bcd" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(512 "\"abc\" =~ /^(a){0,0}/" "^(a){0,0}" nil nil nil nil "abc" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(513 "\"aab\" =~ /^(a){0,0}/" "^(a){0,0}" nil nil nil nil "aab" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(514 "\"bcd\" =~ /^(a){0,1}/" "^(a){0,1}" nil nil nil nil "bcd" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(515 "\"abc\" =~ /^(a){0,1}/" "^(a){0,1}" nil nil nil nil "abc" nil 1 0 "a" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(516 "\"aab\" =~ /^(a){0,1}/" "^(a){0,1}" nil nil nil nil "aab" nil 1 0 "a" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(517 "\"bcd\" =~ /^(a){0,2}/" "^(a){0,2}" nil nil nil nil "bcd" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(518 "\"abc\" =~ /^(a){0,2}/" "^(a){0,2}" nil nil nil nil "abc" nil 1 0 "a" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(519 "\"aab\" =~ /^(a){0,2}/" "^(a){0,2}" nil nil nil nil "aab" nil 1 0 "aa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(520 "\"bcd\" =~ /^(a){0,3}/" "^(a){0,3}" nil nil nil nil "bcd" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(521 "\"abc\" =~ /^(a){0,3}/" "^(a){0,3}" nil nil nil nil "abc" nil 1 0 "a" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(522 "\"aab\" =~ /^(a){0,3}/" "^(a){0,3}" nil nil nil nil "aab" nil 1 0 "aa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(523 "\"aaa\" =~ /^(a){0,3}/" "^(a){0,3}" nil nil nil nil "aaa" nil 1 0 "aaa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(524 "\"bcd\" =~ /^(a){0,}/" "^(a){0,}" nil nil nil nil "bcd" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(525 "\"abc\" =~ /^(a){0,}/" "^(a){0,}" nil nil nil nil "abc" nil 1 0 "a" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(526 "\"aab\" =~ /^(a){0,}/" "^(a){0,}" nil nil nil nil "aab" nil 1 0 "aa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(527 "\"aaa\" =~ /^(a){0,}/" "^(a){0,}" nil nil nil nil "aaa" nil 1 0 "aaa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(528 "\"aaaaaaaa\" =~ /^(a){0,}/" "^(a){0,}" nil nil nil nil "aaaaaaaa" nil 1 0 "aaaaaaaa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(529 "\"bcd\" =~ /^(a){1,1}/" "^(a){1,1}" nil nil nil nil "bcd" nil 1 0 nil nil) +(530 "\"abc\" =~ /^(a){1,1}/" "^(a){1,1}" nil nil nil nil "abc" nil 1 0 "a" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(531 "\"aab\" =~ /^(a){1,1}/" "^(a){1,1}" nil nil nil nil "aab" nil 1 0 "a" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(532 "\"bcd\" =~ /^(a){1,2}/" "^(a){1,2}" nil nil nil nil "bcd" nil 1 0 nil nil) +(533 "\"abc\" =~ /^(a){1,2}/" "^(a){1,2}" nil nil nil nil "abc" nil 1 0 "a" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(534 "\"aab\" =~ /^(a){1,2}/" "^(a){1,2}" nil nil nil nil "aab" nil 1 0 "aa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(535 "\"bcd\" =~ /^(a){1,3}/" "^(a){1,3}" nil nil nil nil "bcd" nil 1 0 nil nil) +(536 "\"abc\" =~ /^(a){1,3}/" "^(a){1,3}" nil nil nil nil "abc" nil 1 0 "a" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(537 "\"aab\" =~ /^(a){1,3}/" "^(a){1,3}" nil nil nil nil "aab" nil 1 0 "aa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(538 "\"aaa\" =~ /^(a){1,3}/" "^(a){1,3}" nil nil nil nil "aaa" nil 1 0 "aaa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(539 "\"bcd\" =~ /^(a){1,}/" "^(a){1,}" nil nil nil nil "bcd" nil 1 0 nil nil) +(540 "\"abc\" =~ /^(a){1,}/" "^(a){1,}" nil nil nil nil "abc" nil 1 0 "a" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(541 "\"aab\" =~ /^(a){1,}/" "^(a){1,}" nil nil nil nil "aab" nil 1 0 "aa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(542 "\"aaa\" =~ /^(a){1,}/" "^(a){1,}" nil nil nil nil "aaa" nil 1 0 "aaa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(543 "\"aaaaaaaa\" =~ /^(a){1,}/" "^(a){1,}" nil nil nil nil "aaaaaaaa" nil 1 0 "aaaaaaaa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(544 "\"borfle\\nbib.gif\\nno\" =~ /.*\\.gif/" ".*\\.gif" nil nil nil nil "borfle +bib.gif +no" nil 1 0 "bib.gif" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(545 "\"borfle\\nbib.gif\\nno\" =~ /.{0,}\\.gif/" ".{0,}\\.gif" nil nil nil nil "borfle +bib.gif +no" nil 1 0 "bib.gif" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(546 "\"borfle\\nbib.gif\\nno\" =~ /.*\\.gif/m" ".*\\.gif" nil t nil nil "borfle +bib.gif +no" nil 1 0 "bib.gif" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(547 "\"borfle\\nbib.gif\\nno\" =~ /.*\\.gif/s" ".*\\.gif" nil nil t nil "borfle +bib.gif +no" nil 1 0 "borfle +bib.gif" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(548 "\"borfle\\nbib.gif\\nno\" =~ /.*\\.gif/ms" ".*\\.gif" nil t t nil "borfle +bib.gif +no" nil 1 0 "borfle +bib.gif" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(549 "\"borfle\\nbib.gif\\nno\" =~ /.*$/" ".*$" nil nil nil nil "borfle +bib.gif +no" nil 1 0 "no" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(550 "\"borfle\\nbib.gif\\nno\" =~ /.*$/m" ".*$" nil t nil nil "borfle +bib.gif +no" nil 1 0 "borfle" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(551 "\"borfle\\nbib.gif\\nno\" =~ /.*$/s" ".*$" nil nil t nil "borfle +bib.gif +no" nil 1 0 "borfle +bib.gif +no" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(552 "\"borfle\\nbib.gif\\nno\" =~ /.*$/ms" ".*$" nil t t nil "borfle +bib.gif +no" nil 1 0 "borfle +bib.gif +no" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(553 "\"borfle\\nbib.gif\\nno\\n\" =~ /.*$/" ".*$" nil nil nil nil "borfle +bib.gif +no +" nil 1 0 "no" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(554 "\"borfle\\nbib.gif\\nno\\n\" =~ /.*$/m" ".*$" nil t nil nil "borfle +bib.gif +no +" nil 1 0 "borfle" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(555 "\"borfle\\nbib.gif\\nno\\n\" =~ /.*$/s" ".*$" nil nil t nil "borfle +bib.gif +no +" nil 1 0 "borfle +bib.gif +no +" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(556 "\"borfle\\nbib.gif\\nno\\n\" =~ /.*$/ms" ".*$" nil t t nil "borfle +bib.gif +no +" nil 1 0 "borfle +bib.gif +no +" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(557 "\"abcde\\n1234Xyz\" =~ /(.*X|^B)/" "(.*X|^B)" nil nil nil nil "abcde +1234Xyz" nil 1 0 "1234X" ("1234X" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(558 "\"BarFoo\" =~ /(.*X|^B)/" "(.*X|^B)" nil nil nil nil "BarFoo" nil 1 0 "B" ("B" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(559 "\"abcde\\nBar\" =~ /(.*X|^B)/" "(.*X|^B)" nil nil nil nil "abcde +Bar" nil 1 0 nil nil) +(560 "\"abcde\\n1234Xyz\" =~ /(.*X|^B)/m" "(.*X|^B)" nil t nil nil "abcde +1234Xyz" nil 1 0 "1234X" ("1234X" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(561 "\"BarFoo\" =~ /(.*X|^B)/m" "(.*X|^B)" nil t nil nil "BarFoo" nil 1 0 "B" ("B" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(562 "\"abcde\\nBar\" =~ /(.*X|^B)/m" "(.*X|^B)" nil t nil nil "abcde +Bar" nil 1 0 "B" ("B" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(563 "\"abcde\\n1234Xyz\" =~ /(.*X|^B)/s" "(.*X|^B)" nil nil t nil "abcde +1234Xyz" nil 1 0 "abcde +1234X" ("abcde +1234X" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(564 "\"BarFoo\" =~ /(.*X|^B)/s" "(.*X|^B)" nil nil t nil "BarFoo" nil 1 0 "B" ("B" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(565 "\"abcde\\nBar\" =~ /(.*X|^B)/s" "(.*X|^B)" nil nil t nil "abcde +Bar" nil 1 0 nil nil) +(566 "\"abcde\\n1234Xyz\" =~ /(.*X|^B)/ms" "(.*X|^B)" nil t t nil "abcde +1234Xyz" nil 1 0 "abcde +1234X" ("abcde +1234X" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(567 "\"BarFoo\" =~ /(.*X|^B)/ms" "(.*X|^B)" nil t t nil "BarFoo" nil 1 0 "B" ("B" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(568 "\"abcde\\nBar\" =~ /(.*X|^B)/ms" "(.*X|^B)" nil t t nil "abcde +Bar" nil 1 0 "B" ("B" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(569 "\"abcde\\n1234Xyz\" =~ /(?s)(.*X|^B)/" "(?s)(.*X|^B)" nil nil nil nil "abcde +1234Xyz" nil 1 0 "abcde +1234X" ("abcde +1234X" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(570 "\"BarFoo\" =~ /(?s)(.*X|^B)/" "(?s)(.*X|^B)" nil nil nil nil "BarFoo" nil 1 0 "B" ("B" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(571 "\"abcde\\nBar\" =~ /(?s)(.*X|^B)/" "(?s)(.*X|^B)" nil nil nil nil "abcde +Bar" nil 1 0 nil nil) +(572 "\"abcde\\n1234Xyz\" =~ /(?s:.*X|^B)/" "(?s:.*X|^B)" nil nil nil nil "abcde +1234Xyz" nil 1 0 "abcde +1234X" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(573 "\"BarFoo\" =~ /(?s:.*X|^B)/" "(?s:.*X|^B)" nil nil nil nil "BarFoo" nil 1 0 "B" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(574 "\"abcde\\nBar\" =~ /(?s:.*X|^B)/" "(?s:.*X|^B)" nil nil nil nil "abcde +Bar" nil 1 0 nil nil) +(575 "\"abc\\nB\" =~ /^.*B/" "^.*B" nil nil nil nil "abc +B" nil 1 0 nil nil) +(576 "\"abc\\nB\" =~ /(?s)^.*B/" "(?s)^.*B" nil nil nil nil "abc +B" nil 1 0 "abc +B" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(577 "\"abc\\nB\" =~ /(?m)^.*B/" "(?m)^.*B" nil nil nil nil "abc +B" nil 1 0 "B" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(578 "\"abc\\nB\" =~ /(?ms)^.*B/" "(?ms)^.*B" nil nil nil nil "abc +B" nil 1 0 "abc +B" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(579 "\"abc\\nB\" =~ /(?ms)^B/" "(?ms)^B" nil nil nil nil "abc +B" nil 1 0 "B" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(580 "\"B\\n\" =~ /(?s)B$/" "(?s)B$" nil nil nil nil "B +" nil 1 0 "B" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(581 "\"123456654321\" =~ /^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/" "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]" nil nil nil nil "123456654321" nil 1 0 "123456654321" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(582 "\"123456654321\" =~ /^\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d/" "^\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d" nil nil nil nil "123456654321" nil 1 0 "123456654321" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(583 "\"123456654321\" =~ /^[\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d]/" "^[\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d][\\d]" nil nil nil nil "123456654321" nil 1 0 "123456654321" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(584 "\"abcabcabcabc\" =~ /^[abc]{12}/" "^[abc]{12}" nil nil nil nil "abcabcabcabc" nil 1 0 "abcabcabcabc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(585 "\"abcabcabcabc\" =~ /^[a-c]{12}/" "^[a-c]{12}" nil nil nil nil "abcabcabcabc" nil 1 0 "abcabcabcabc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(586 "\"abcabcabcabc\" =~ /^(a|b|c){12}/" "^(a|b|c){12}" nil nil nil nil "abcabcabcabc" nil 1 0 "abcabcabcabc" ("c" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(587 "\"n\" =~ /^[abcdefghijklmnopqrstuvwxy0123456789]/" "^[abcdefghijklmnopqrstuvwxy0123456789]" nil nil nil nil "n" nil 1 0 "n" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(588 "\"z\" =~ /^[abcdefghijklmnopqrstuvwxy0123456789]/" "^[abcdefghijklmnopqrstuvwxy0123456789]" nil nil nil nil "z" nil 1 0 nil nil) +(589 "\"abcd\" =~ /abcde{0,0}/" "abcde{0,0}" nil nil nil nil "abcd" nil 1 0 "abcd" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(590 "\"abce\" =~ /abcde{0,0}/" "abcde{0,0}" nil nil nil nil "abce" nil 1 0 nil nil) +(591 "\"abe\" =~ /ab[cd]{0,0}e/" "ab[cd]{0,0}e" nil nil nil nil "abe" nil 1 0 "abe" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(592 "\"abcde\" =~ /ab[cd]{0,0}e/" "ab[cd]{0,0}e" nil nil nil nil "abcde" nil 1 0 nil nil) +(593 "\"abd\" =~ /ab(c){0,0}d/" "ab(c){0,0}d" nil nil nil nil "abd" nil 1 0 "abd" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(594 "\"abcd\" =~ /ab(c){0,0}d/" "ab(c){0,0}d" nil nil nil nil "abcd" nil 1 0 nil nil) +(595 "\"a\" =~ /a(b*)/" "a(b*)" nil nil nil nil "a" nil 1 0 "a" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(596 "\"ab\" =~ /a(b*)/" "a(b*)" nil nil nil nil "ab" nil 1 0 "ab" ("b" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(597 "\"abbbb\" =~ /a(b*)/" "a(b*)" nil nil nil nil "abbbb" nil 1 0 "abbbb" ("bbbb" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(598 "\"bbbbb\" =~ /a(b*)/" "a(b*)" nil nil nil nil "bbbbb" nil 1 0 nil nil) +(599 "\"abe\" =~ /ab\\d{0}e/" "ab\\d{0}e" nil nil nil nil "abe" nil 1 0 "abe" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(600 "\"ab1e\" =~ /ab\\d{0}e/" "ab\\d{0}e" nil nil nil nil "ab1e" nil 1 0 nil nil) +(601 "\"the \\\"quick\\\" brown fox\" =~ /\"([^\\\\\"]+|\\\\.)*\"/" "\"([^\\\\\"]+|\\\\.)*\"" nil nil nil nil "the \"quick\" brown fox" nil 1 0 "\"quick\"" ("quick" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(602 "\"\\\"the \\\\\\\"quick\\\\\\\" brown fox\\\"\" =~ /\"([^\\\\\"]+|\\\\.)*\"/" "\"([^\\\\\"]+|\\\\.)*\"" nil nil nil nil "\"the \\\"quick\\\" brown fox\"" nil 1 0 "\"the \\\"quick\\\" brown fox\"" (" brown fox" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(603 "\"abc\" =~ /.*?/" ".*?" nil nil nil nil "abc" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(604 "\"abc\" =~ /\\b/" "\\b" nil nil nil nil "abc" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(605 "\"abc\" =~ /\\b/" "\\b" nil nil nil nil "abc" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(606 "\"abc\" =~ /(?#)/" "" nil nil nil nil "abc" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(607 "\"43.Word Processor
(N-1286)
Lega lstaff.comCA - Statewide\" =~ /]{0,})>]{0,})>([\\d]{0,}\\.)(.*)((
([\\w\\W\\s\\d][^<>]{0,})|[\\s]{0,}))<\\/a><\\/TD>]{0,})>([\\w\\W\\s\\d][^<>]{0,})<\\/TD>]{0,})>([\\w\\W\\s\\d][^<>]{0,})<\\/TD><\\/TR>/is" "]{0,})>]{0,})>([\\d]{0,}\\.)(.*)((
([\\w\\W\\s\\d][^<>]{0,})|[\\s]{0,}))<\\/a><\\/TD>]{0,})>([\\w\\W\\s\\d][^<>]{0,})<\\/TD>]{0,})>([\\w\\W\\s\\d][^<>]{0,})<\\/TD><\\/TR>" t nil t nil "43.Word Processor
(N-1286)
Lega lstaff.comCA - Statewide" nil 1 0 "43.Word Processor
(N-1286)
Lega lstaff.comCA - Statewide" (" BGCOLOR='#DBE9E9'" " align=left valign=top" "43." "Word Processor
(N-1286)" "" "" nil " align=left valign=top" "Lega lstaff.com" " align=left valign=top" "CA - Statewide" nil nil nil nil nil)) +(608 "\"acb\" =~ /a[^a]b/" "a[^a]b" nil nil nil nil "acb" nil 1 0 "acb" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(609 "\"a\\nb\" =~ /a[^a]b/" "a[^a]b" nil nil nil nil "a +b" nil 1 0 "a +b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(610 "\"acb\" =~ /a.b/" "a.b" nil nil nil nil "acb" nil 1 0 "acb" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(611 "\"a\\nb\" =~ /a.b/" "a.b" nil nil nil nil "a +b" nil 1 0 nil nil) +(612 "\"acb\" =~ /a[^a]b/s" "a[^a]b" nil nil t nil "acb" nil 1 0 "acb" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(613 "\"a\\nb\" =~ /a[^a]b/s" "a[^a]b" nil nil t nil "a +b" nil 1 0 "a +b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(614 "\"acb\" =~ /a.b/s" "a.b" nil nil t nil "acb" nil 1 0 "acb" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(615 "\"a\\nb\" =~ /a.b/s" "a.b" nil nil t nil "a +b" nil 1 0 "a +b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(616 "\"bac\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "bac" nil 1 0 "bac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(617 "\"bbac\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "bbac" nil 1 0 "bbac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(618 "\"bbbac\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "bbbac" nil 1 0 "bbbac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(619 "\"bbbbac\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "bbbbac" nil 1 0 "bbbbac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(620 "\"bbbbbac\" =~ /^(b+?|a){1,2}?c/" "^(b+?|a){1,2}?c" nil nil nil nil "bbbbbac" nil 1 0 "bbbbbac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(621 "\"bac\" =~ /^(b+|a){1,2}?c/" "^(b+|a){1,2}?c" nil nil nil nil "bac" nil 1 0 "bac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(622 "\"bbac\" =~ /^(b+|a){1,2}?c/" "^(b+|a){1,2}?c" nil nil nil nil "bbac" nil 1 0 "bbac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(623 "\"bbbac\" =~ /^(b+|a){1,2}?c/" "^(b+|a){1,2}?c" nil nil nil nil "bbbac" nil 1 0 "bbbac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(624 "\"bbbbac\" =~ /^(b+|a){1,2}?c/" "^(b+|a){1,2}?c" nil nil nil nil "bbbbac" nil 1 0 "bbbbac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(625 "\"bbbbbac\" =~ /^(b+|a){1,2}?c/" "^(b+|a){1,2}?c" nil nil nil nil "bbbbbac" nil 1 0 "bbbbbac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(626 "\"x\\nb\\n\" =~ /(?!\\A)x/m" "(?!\\A)x" nil t nil nil "x +b +" nil 1 0 nil nil) +(627 "\"a\\bx\\n\" =~ /(?!\\A)x/m" "(?!\\A)x" nil t nil nil ("a" 8 "x" 10) nil 1 0 "x" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(628 "\"\\0{ab}\" =~ /\\x0{ab}/" "\\x0{ab}" nil nil nil nil ("" 0 "{ab}") nil 1 0 ("" 0 "{ab}") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(629 "\"CD\" =~ /(A|B)*?CD/" "(A|B)*?CD" nil nil nil nil "CD" nil 1 0 "CD" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(630 "\"CD\" =~ /(A|B)*CD/" "(A|B)*CD" nil nil nil nil "CD" nil 1 0 "CD" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(631 "\"ABABAB\" =~ /(AB)*?\\1/" "(AB)*?\\1" nil nil nil nil "ABABAB" nil 1 0 "ABAB" ("AB" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(632 "\"ABABAB\" =~ /(AB)*\\1/" "(AB)*\\1" nil nil nil nil "ABABAB" nil 1 0 "ABABAB" ("AB" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(633 "\"doesn't matter\" =~ /(/" "(" nil nil nil nil "doesn't matter" t 1 0 nil nil) +(634 "\"doesn't matter\" =~ /(x)\\2/" "(x)\\2" nil nil nil nil "doesn't matter" t 1 0 nil nil) +(635 "\"aaaaaaaaaac\" =~ /((a{0,5}){0,5}){0,5}[c]/" "((a{0,5}){0,5}){0,5}[c]" nil nil nil nil "aaaaaaaaaac" nil 1 0 "aaaaaaaaaac" ("" "" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(636 "\"aaaaaaaaaa\" =~ /((a{0,5}){0,5}){0,5}[c]/" "((a{0,5}){0,5}){0,5}[c]" nil nil nil nil "aaaaaaaaaa" nil 1 0 nil nil) +(637 "\"aaaaaaaaaac\" =~ /((a{0,5}){0,5})*[c]/" "((a{0,5}){0,5})*[c]" nil nil nil nil "aaaaaaaaaac" nil 1 0 "aaaaaaaaaac" ("" "" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(638 "\"aaaaaaaaaa\" =~ /((a{0,5}){0,5})*[c]/" "((a{0,5}){0,5})*[c]" nil nil nil nil "aaaaaaaaaa" nil 1 0 nil nil) +(639 "\"a\" =~ /(\\b)*a/" "(\\b)*a" nil nil nil nil "a" nil 1 0 "a" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(640 "\"ab\" =~ /(a)*b/" "(a)*b" nil nil nil nil "ab" nil 1 0 "ab" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(641 "\"ab\" =~ /(a|)*b/" "(a|)*b" nil nil nil nil "ab" nil 1 0 "ab" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(642 "\"b\" =~ /(a|)*b/" "(a|)*b" nil nil nil nil "b" nil 1 0 "b" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(643 "\"x\" =~ /(a|)*b/" "(a|)*b" nil nil nil nil "x" nil 1 0 nil nil) +(644 "\"abab\" =~ /^(?:(a)|(b))*\\1\\2$/" "^(?:(a)|(b))*\\1\\2$" nil nil nil nil "abab" nil 1 0 "abab" ("a" "b" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(645 "\"abcxabcydef\" =~ /abc[^x]def/" "abc[^x]def" nil nil nil nil "abcxabcydef" nil 1 0 "abcydef" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(646 "\"aax\" =~ /^(a|\\1x)*$/" "^(a|\\1x)*$" nil nil nil nil "aax" nil 1 0 "aax" ("ax" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(647 "\"aaxa\" =~ /^(a|\\1x)*$/" "^(a|\\1x)*$" nil nil nil nil "aaxa" nil 1 0 "aaxa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(648 "\"@{['']}\" =~ /(?#)/" "" nil nil nil nil "" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(649 "\"ab\" =~ /^(?:(a)|(b))*$/" "^(?:(a)|(b))*$" nil nil nil nil "ab" nil 1 0 "ab" ("a" "b" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(650 "\"a\" =~ /[\\0]/" "[\\0]" nil nil nil nil "a" nil 1 0 nil nil) +(651 "\"\\0\" =~ /[\\0]/" "[\\0]" nil nil nil nil ("" 0) nil 1 0 ("" 0) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(652 "\"a\" =~ /[\\1]/" "[\\1]" nil nil nil nil "a" nil 1 0 nil nil) +(653 "\"\\1\" =~ /[\\1]/" "[\\1]" nil nil nil nil ("" 1) nil 1 0 ("" 1) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(654 "\"doesn't matter\" =~ /\\10()()()()()()()()()/" "\\10()()()()()()()()()" nil nil nil nil "doesn't matter" nil 1 0 nil nil) +(655 "\"a\" =~ /\\10()()()()()()()()()()/" "\\10()()()()()()()()()()" nil nil nil nil "a" nil 1 0 nil nil) +(656 "\"ab\" =~ /a(?<)b/" "a(?<)b" nil nil nil nil "ab" nil 1 0 "ab" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(657 "\"doesn't matter\" =~ /[]/" "[]" nil nil nil nil "doesn't matter" t 1 0 nil nil) +(658 "\"doesn't matter\" =~ /[\\]/" "[\\]" nil nil nil nil "doesn't matter" t 1 0 nil nil) +(659 "\"a\" =~ /()/" "()" nil nil nil nil "a" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(660 "\"x\" =~ /[\\x]/" "[\\x]" nil nil nil nil "x" nil 1 0 nil nil) +(661 "\"\\0\" =~ /[\\x]/" "[\\x]" nil nil nil nil ("" 0) nil 1 0 ("" 0) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(662 "\"a\" =~ /((a)*)*/" "((a)*)*" nil nil nil nil "a" nil 1 0 "a" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(663 "\"a\" =~ /()a\\1/" "()a\\1" nil nil nil nil "a" nil 1 0 "a" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(664 "\"a\" =~ /a\\1()/" "a\\1()" nil nil nil nil "a" nil 1 0 nil nil) +(665 "\"aaa\" =~ /a(?i)a(?-i)a/" "a(?i)a(?-i)a" nil nil nil nil "aaa" nil 1 0 "aaa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(666 "\"aAa\" =~ /a(?i)a(?-i)a/" "a(?i)a(?-i)a" nil nil nil nil "aAa" nil 1 0 "aAa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(667 "\"aAA\" =~ /a(?i)a(?-i)a/" "a(?i)a(?-i)a" nil nil nil nil "aAA" nil 1 0 nil nil) +(668 "\"aaaaa\" =~ /a(?i)a(?-i)a(?i)a(?-i)a/" "a(?i)a(?-i)a(?i)a(?-i)a" nil nil nil nil "aaaaa" nil 1 0 "aaaaa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(669 "\"aAaAa\" =~ /a(?i)a(?-i)a(?i)a(?-i)a/" "a(?i)a(?-i)a(?i)a(?-i)a" nil nil nil nil "aAaAa" nil 1 0 "aAaAa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(670 "\"AaAaA\" =~ /a(?i)a(?-i)a(?i)a(?-i)a/" "a(?i)a(?-i)a(?i)a(?-i)a" nil nil nil nil "AaAaA" nil 1 0 nil nil) +(671 "\"aAAAa\" =~ /a(?i)a(?-i)a(?i)a(?-i)a/" "a(?i)a(?-i)a(?i)a(?-i)a" nil nil nil nil "aAAAa" nil 1 0 nil nil) +(672 "\"AaaaA\" =~ /a(?i)a(?-i)a(?i)a(?-i)a/" "a(?i)a(?-i)a(?i)a(?-i)a" nil nil nil nil "AaaaA" nil 1 0 nil nil) +(673 "\"AAAAA\" =~ /a(?i)a(?-i)a(?i)a(?-i)a/" "a(?i)a(?-i)a(?i)a(?-i)a" nil nil nil nil "AAAAA" nil 1 0 nil nil) +(674 "\"aaAAA\" =~ /a(?i)a(?-i)a(?i)a(?-i)a/" "a(?i)a(?-i)a(?i)a(?-i)a" nil nil nil nil "aaAAA" nil 1 0 nil nil) +(675 "\"AAaaa\" =~ /a(?i)a(?-i)a(?i)a(?-i)a/" "a(?i)a(?-i)a(?i)a(?-i)a" nil nil nil nil "AAaaa" nil 1 0 nil nil) +(676 "\"a\" =~ /\\x/" "\\x" nil nil nil nil "a" nil 1 0 nil nil) +(677 "\"X\" =~ /\\x/" "\\x" nil nil nil nil "X" nil 1 0 nil nil) +(678 "\"\\0\" =~ /\\x/" "\\x" nil nil nil nil ("" 0) nil 1 0 ("" 0) (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(679 "\"a\" =~ /[a-c-e]/" "[a-c-e]" nil nil nil nil "a" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(680 "\"b\" =~ /[a-c-e]/" "[a-c-e]" nil nil nil nil "b" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(681 "\"d\" =~ /[a-c-e]/" "[a-c-e]" nil nil nil nil "d" nil 1 0 nil nil) +(682 "\"-\" =~ /[a-c-e]/" "[a-c-e]" nil nil nil nil "-" nil 1 0 "-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(683 "\"b\" =~ /[b-\\d]/" "[b-\\d]" nil nil nil nil "b" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(684 "\"c\" =~ /[b-\\d]/" "[b-\\d]" nil nil nil nil "c" nil 1 0 nil nil) +(685 "\"d\" =~ /[b-\\d]/" "[b-\\d]" nil nil nil nil "d" nil 1 0 nil nil) +(686 "\"-\" =~ /[b-\\d]/" "[b-\\d]" nil nil nil nil "-" nil 1 0 "-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(687 "\"1\" =~ /[b-\\d]/" "[b-\\d]" nil nil nil nil "1" nil 1 0 "1" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(688 "\"d\" =~ /[\\d-f]/" "[\\d-f]" nil nil nil nil "d" nil 1 0 nil nil) +(689 "\"e\" =~ /[\\d-f]/" "[\\d-f]" nil nil nil nil "e" nil 1 0 nil nil) +(690 "\"f\" =~ /[\\d-f]/" "[\\d-f]" nil nil nil nil "f" nil 1 0 "f" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(691 "\"-\" =~ /[\\d-f]/" "[\\d-f]" nil nil nil nil "-" nil 1 0 "-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(692 "\"1\" =~ /[\\d-f]/" "[\\d-f]" nil nil nil nil "1" nil 1 0 "1" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(693 "\"doesn't matter\" =~ /[/" "[" nil nil nil nil "doesn't matter" t 1 0 nil nil) +(694 "\"]\" =~ /]/" "]" nil nil nil nil "]" nil 1 0 "]" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(695 "\"a\" =~ /]/" "]" nil nil nil nil "a" nil 1 0 nil nil) +(696 "\"doesn't matter\" =~ /[]/" "[]" nil nil nil nil "doesn't matter" t 1 0 nil nil) +(697 "\"-\" =~ /[-a-c]/" "[-a-c]" nil nil nil nil "-" nil 1 0 "-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(698 "\"a\" =~ /[-a-c]/" "[-a-c]" nil nil nil nil "a" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(699 "\"b\" =~ /[-a-c]/" "[-a-c]" nil nil nil nil "b" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(700 "\"d\" =~ /[-a-c]/" "[-a-c]" nil nil nil nil "d" nil 1 0 nil nil) +(701 "\"-\" =~ /[a-c-]/" "[a-c-]" nil nil nil nil "-" nil 1 0 "-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(702 "\"a\" =~ /[a-c-]/" "[a-c-]" nil nil nil nil "a" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(703 "\"b\" =~ /[a-c-]/" "[a-c-]" nil nil nil nil "b" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(704 "\"d\" =~ /[a-c-]/" "[a-c-]" nil nil nil nil "d" nil 1 0 nil nil) +(705 "\"a\" =~ /[-]/" "[-]" nil nil nil nil "a" nil 1 0 nil nil) +(706 "\"-\" =~ /[-]/" "[-]" nil nil nil nil "-" nil 1 0 "-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(707 "\"a\" =~ /[--]/" "[--]" nil nil nil nil "a" nil 1 0 nil nil) +(708 "\"-\" =~ /[--]/" "[--]" nil nil nil nil "-" nil 1 0 "-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(709 "\"a\" =~ /[---]/" "[---]" nil nil nil nil "a" nil 1 0 nil nil) +(710 "\"-\" =~ /[---]/" "[---]" nil nil nil nil "-" nil 1 0 "-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(711 "\"-\" =~ /[--b]/" "[--b]" nil nil nil nil "-" nil 1 0 "-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(712 "\"a\" =~ /[--b]/" "[--b]" nil nil nil nil "a" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(713 "\"c\" =~ /[--b]/" "[--b]" nil nil nil nil "c" nil 1 0 nil nil) +(714 "\"doesn't matter\" =~ /[b--]/" "[b--]" nil nil nil nil "doesn't matter" t 1 0 nil nil) +(715 "\"a{\" =~ /a{/" "a{" nil nil nil nil "a{" nil 1 0 "a{" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(716 "\"a{}\" =~ /a{}/" "a{}" nil nil nil nil "a{}" nil 1 0 "a{}" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(717 "\"a{3\" =~ /a{3/" "a{3" nil nil nil nil "a{3" nil 1 0 "a{3" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(718 "\"a{3,\" =~ /a{3,/" "a{3," nil nil nil nil "a{3," nil 1 0 "a{3," (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(719 "\"a{3,3}\" =~ /a{3, 3}/" "a{3, 3}" nil nil nil nil "a{3,3}" nil 1 0 nil nil) +(720 "\"a{3, 3}\" =~ /a{3, 3}/" "a{3, 3}" nil nil nil nil "a{3, 3}" nil 1 0 "a{3, 3}" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(721 "\"aaa\" =~ /a{3, 3}/" "a{3, 3}" nil nil nil nil "aaa" nil 1 0 nil nil) +(722 "\"a{3,3}\" =~ /a{3, 3}/x" "a{3, 3}" nil nil nil t "a{3,3}" nil 1 0 "a{3,3}" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(723 "\"a{3, 3}\" =~ /a{3, 3}/x" "a{3, 3}" nil nil nil t "a{3, 3}" nil 1 0 nil nil) +(724 "\"aaa\" =~ /a{3, 3}/x" "a{3, 3}" nil nil nil t "aaa" nil 1 0 nil nil) +(725 "\"a{3,}\" =~ /a{3, }/" "a{3, }" nil nil nil nil "a{3,}" nil 1 0 nil nil) +(726 "\"a{3, }\" =~ /a{3, }/" "a{3, }" nil nil nil nil "a{3, }" nil 1 0 "a{3, }" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(727 "\"aaa\" =~ /a{3, }/" "a{3, }" nil nil nil nil "aaa" nil 1 0 nil nil) +(728 "\"a{3,}\" =~ /a{3, }/x" "a{3, }" nil nil nil t "a{3,}" nil 1 0 "a{3,}" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(729 "\"a{3, }\" =~ /a{3, }/x" "a{3, }" nil nil nil t "a{3, }" nil 1 0 nil nil) +(730 "\"aaa\" =~ /a{3, }/x" "a{3, }" nil nil nil t "aaa" nil 1 0 nil nil) +(731 "\"\\0 x\" =~ /\\x x/" "\\x x" nil nil nil nil ("" 0 " x") nil 1 0 ("" 0 " x") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(732 "\"\\0x\" =~ /\\x x/" "\\x x" nil nil nil nil ("" 0 "x") nil 1 0 nil nil) +(733 "\"\\0 x\" =~ /\\x x/x" "\\x x" nil nil nil t ("" 0 " x") nil 1 0 nil nil) +(734 "\"\\0x\" =~ /\\x x/x" "\\x x" nil nil nil t ("" 0 "x") nil 1 0 ("" 0 "x") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(735 "\"\\0003\" =~ /\\x 3/" "\\x 3" nil nil nil nil ("" 0 "3") nil 1 0 nil nil) +(736 "\"\\000 3\" =~ /\\x 3/" "\\x 3" nil nil nil nil ("" 0 " 3") nil 1 0 ("" 0 " 3") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(737 "\"x3\" =~ /\\x 3/" "\\x 3" nil nil nil nil "x3" nil 1 0 nil nil) +(738 "\"x 3\" =~ /\\x 3/" "\\x 3" nil nil nil nil "x 3" nil 1 0 nil nil) +(739 "\"\\0003\" =~ /\\x 3/x" "\\x 3" nil nil nil t ("" 0 "3") nil 1 0 ("" 0 "3") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(740 "\"\\000 3\" =~ /\\x 3/x" "\\x 3" nil nil nil t ("" 0 " 3") nil 1 0 nil nil) +(741 "\"x3\" =~ /\\x 3/x" "\\x 3" nil nil nil t "x3" nil 1 0 nil nil) +(742 "\"x 3\" =~ /\\x 3/x" "\\x 3" nil nil nil t "x 3" nil 1 0 nil nil) +(743 "\"a\" =~ /^a{ 1}$/" "^a{ 1}$" nil nil nil nil "a" nil 1 0 nil nil) +(744 "\"a{ 1}\" =~ /^a{ 1}$/" "^a{ 1}$" nil nil nil nil "a{ 1}" nil 1 0 "a{ 1}" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(745 "\"a{1}\" =~ /^a{ 1}$/" "^a{ 1}$" nil nil nil nil "a{1}" nil 1 0 nil nil) +(746 "\"a\" =~ /^a{ 1}$/x" "^a{ 1}$" nil nil nil t "a" nil 1 0 nil nil) +(747 "\"a{ 1}\" =~ /^a{ 1}$/x" "^a{ 1}$" nil nil nil t "a{ 1}" nil 1 0 nil nil) +(748 "\"a{1}\" =~ /^a{ 1}$/x" "^a{ 1}$" nil nil nil t "a{1}" nil 1 0 "a{1}" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(749 "\"{}\" =~ /{}/" "{}" nil nil nil nil "{}" nil 1 0 "{}" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(750 "\"a\" =~ /{}/" "{}" nil nil nil nil "a" nil 1 0 nil nil) +(751 "\"doesn't matter\" =~ /{1}/" "{1}" nil nil nil nil "doesn't matter" t 1 0 nil nil) +(752 "\"doesn't matter\" =~ /*/" "*" nil nil nil nil "doesn't matter" t 1 0 nil nil) +(753 "\"x\" =~ /|/" "|" nil nil nil nil "x" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(754 "\"\\0000\" =~ /\\0000/" "\\0000" nil nil nil nil ("" 0 "0") nil 1 0 ("" 0 "0") (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(755 "\"ab\" =~ /a(?<)b/" "a(?<)b" nil nil nil nil "ab" nil 1 0 "ab" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(756 "\"ab\" =~ /a(?i)b/" "a(?i)b" nil nil nil nil "ab" nil 1 0 "ab" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(757 "\"aB\" =~ /a(?i)b/" "a(?i)b" nil nil nil nil "aB" nil 1 0 "aB" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(758 "\"Ab\" =~ /a(?i)b/" "a(?i)b" nil nil nil nil "Ab" nil 1 0 nil nil) +(759 "\"doesn't matter\" =~ /a(?i=a)/" "a(?i=a)" nil nil nil nil "doesn't matter" t 1 0 nil nil) +(760 "\"aa\" =~ /a(?<=a){3000}a/" "a(?<=a){3000}a" nil nil nil nil "aa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(761 "\"xa\" =~ /a(?<=a){3000}a/" "a(?<=a){3000}a" nil nil nil nil "xa" nil 1 0 nil nil) +(762 "\"ax\" =~ /a(?<=a){3000}a/" "a(?<=a){3000}a" nil nil nil nil "ax" nil 1 0 nil nil) +(763 "\"aa\" =~ /a(?!=a){3000}a/" "a(?!=a){3000}a" nil nil nil nil "aa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(764 "\"ax\" =~ /a(?!=a){3000}a/" "a(?!=a){3000}a" nil nil nil nil "ax" nil 1 0 nil nil) +(765 "\"xa\" =~ /a(?!=a){3000}a/" "a(?!=a){3000}a" nil nil nil nil "xa" nil 1 0 nil nil) +(766 "\"aa\" =~ /a(){3000}a/" "a(){3000}a" nil nil nil nil "aa" nil 1 0 "aa" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(767 "\"ax\" =~ /a(){3000}a/" "a(){3000}a" nil nil nil nil "ax" nil 1 0 nil nil) +(768 "\"xa\" =~ /a(){3000}a/" "a(){3000}a" nil nil nil nil "xa" nil 1 0 nil nil) +(769 "\"aa\" =~ /a(?:){3000}a/" "a(?:){3000}a" nil nil nil nil "aa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(770 "\"ax\" =~ /a(?:){3000}a/" "a(?:){3000}a" nil nil nil nil "ax" nil 1 0 nil nil) +(771 "\"aa\" =~ /a(?<=a)*a/" "a(?<=a)*a" nil nil nil nil "aa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(772 "\"ax\" =~ /a(?<=a)*a/" "a(?<=a)*a" nil nil nil nil "ax" nil 1 0 nil nil) +(773 "\"xa\" =~ /a(?<=a)*a/" "a(?<=a)*a" nil nil nil nil "xa" nil 1 0 nil nil) +(774 "\"aa\" =~ /a(?!=a)*a/" "a(?!=a)*a" nil nil nil nil "aa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(775 "\"ax\" =~ /a(?!=a)*a/" "a(?!=a)*a" nil nil nil nil "ax" nil 1 0 nil nil) +(776 "\"xa\" =~ /a(?!=a)*a/" "a(?!=a)*a" nil nil nil nil "xa" nil 1 0 nil nil) +(777 "\"aa\" =~ /a()*a/" "a()*a" nil nil nil nil "aa" nil 1 0 "aa" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(778 "\"ax\" =~ /a()*a/" "a()*a" nil nil nil nil "ax" nil 1 0 nil nil) +(779 "\"xa\" =~ /a()*a/" "a()*a" nil nil nil nil "xa" nil 1 0 nil nil) +(780 "\"aa\" =~ /a(?:)*a/" "a(?:)*a" nil nil nil nil "aa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(781 "\"ax\" =~ /a(?:)*a/" "a(?:)*a" nil nil nil nil "ax" nil 1 0 nil nil) +(782 "\"xa\" =~ /a(?:)*a/" "a(?:)*a" nil nil nil nil "xa" nil 1 0 nil nil) +(783 "\"aa\" =~ /x(?<=a)*a/" "x(?<=a)*a" nil nil nil nil "aa" nil 1 0 nil nil) +(784 "\"xa\" =~ /x(?<=a)*a/" "x(?<=a)*a" nil nil nil nil "xa" nil 1 0 "xa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(785 "\"ax\" =~ /x(?<=a)*a/" "x(?<=a)*a" nil nil nil nil "ax" nil 1 0 nil nil) +(786 "\"aa\" =~ /a(?<=(a))*\\1/" "a(?<=(a))*\\1" nil nil nil nil "aa" nil 1 0 "aa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(787 "\"aa\" =~ /a(?<=(a))*?\\1/" "a(?<=(a))*?\\1" nil nil nil nil "aa" nil 1 0 "aa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(788 "\"aa\" =~ /(?=(a)\\1)*aa/" "(?=(a)\\1)*aa" nil nil nil nil "aa" nil 1 0 "aa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(789 "\"aaaaabbbbb\" =~ /^((a|b){2,5}){2}$/" "^((a|b){2,5}){2}$" nil nil nil nil "aaaaabbbbb" nil 1 0 "aaaaabbbbb" ("bbbbb" "b" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(790 "\"babc\" =~ /^(b*|ba){1,2}bc/" "^(b*|ba){1,2}bc" nil nil nil nil "babc" nil 1 0 "babc" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(791 "\"bbabc\" =~ /^(b*|ba){1,2}bc/" "^(b*|ba){1,2}bc" nil nil nil nil "bbabc" nil 1 0 "bbabc" ("ba" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(792 "\"bababc\" =~ /^(b*|ba){1,2}bc/" "^(b*|ba){1,2}bc" nil nil nil nil "bababc" nil 1 0 "bababc" ("ba" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(793 "\"bababbc\" =~ /^(b*|ba){1,2}bc/" "^(b*|ba){1,2}bc" nil nil nil nil "bababbc" nil 1 0 nil nil) +(794 "\"babababc\" =~ /^(b*|ba){1,2}bc/" "^(b*|ba){1,2}bc" nil nil nil nil "babababc" nil 1 0 nil nil) +(795 "\"aaaaac\" =~ /^a{4,5}(?:c|a)c$/" "^a{4,5}(?:c|a)c$" nil nil nil nil "aaaaac" nil 1 0 "aaaaac" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(796 "\"aaaaaac\" =~ /^a{4,5}(?:c|a)c$/" "^a{4,5}(?:c|a)c$" nil nil nil nil "aaaaaac" nil 1 0 "aaaaaac" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(797 "\"aaaaac\" =~ /^(a|){4,5}(?:c|a)c$/" "^(a|){4,5}(?:c|a)c$" nil nil nil nil "aaaaac" nil 1 0 "aaaaac" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(798 "\"aaaaaac\" =~ /^(a|){4,5}(?:c|a)c$/" "^(a|){4,5}(?:c|a)c$" nil nil nil nil "aaaaaac" nil 1 0 "aaaaaac" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(799 "\"eeexabc\" =~ /(?m:^).abc$/" "(?m:^).abc$" nil nil nil nil "eeexabc" nil 1 0 nil nil) +(800 "\"eee\\nxabc\" =~ /(?m:^).abc$/" "(?m:^).abc$" nil nil nil nil "eee +xabc" nil 1 0 "xabc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(801 "\"abc\" =~ /(?m:^)abc/" "(?m:^)abc" nil nil nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(802 "\"\\nabc\" =~ /(?m:^)abc/" "(?m:^)abc" nil nil nil nil " +abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(803 "\"abc\" =~ +/^abc/" "^abc" nil nil nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(804 "\"\\nabc\" =~ +/^abc/" "^abc" nil nil nil nil " +abc" nil 1 0 nil nil) +(805 "\"abc\" =~ /\\Aabc/" "\\Aabc" nil nil nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(806 "\"\\nabc\" =~ /\\Aabc/" "\\Aabc" nil nil nil nil " +abc" nil 1 0 nil nil) +(807 "\"foo\" =~ /(?.*/)foo\"" "(?>.*/)foo" nil nil nil nil "/this/is/a/very/long/line/in/deed/with/very/many/slashes/in/it/you/see/" nil 1 0 nil nil) +(826 "\"/this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo\" =~ \"(?>.*/)foo\"" "(?>.*/)foo" nil nil nil nil "/this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo" nil 1 0 "/this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(827 "\"1.230003938\" =~ /(?>(\\.\\d\\d[1-9]?))\\d+/" "(?>(\\.\\d\\d[1-9]?))\\d+" nil nil nil nil "1.230003938" nil 1 0 ".230003938" (".23" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(828 "\"1.875000282\" =~ /(?>(\\.\\d\\d[1-9]?))\\d+/" "(?>(\\.\\d\\d[1-9]?))\\d+" nil nil nil nil "1.875000282" nil 1 0 ".875000282" (".875" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(829 "\"1.235\" =~ /(?>(\\.\\d\\d[1-9]?))\\d+/" "(?>(\\.\\d\\d[1-9]?))\\d+" nil nil nil nil "1.235" nil 1 0 nil nil) +(830 "\"now is the time for all good men to come to the aid of the party\" =~ /^((?>\\w+)|(?>\\s+))*$/" "^((?>\\w+)|(?>\\s+))*$" nil nil nil nil "now is the time for all good men to come to the aid of the party" nil 1 0 "now is the time for all good men to come to the aid of the party" ("party" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(831 "\"this is not a line with only words and spaces!\" =~ /^((?>\\w+)|(?>\\s+))*$/" "^((?>\\w+)|(?>\\s+))*$" nil nil nil nil "this is not a line with only words and spaces!" nil 1 0 nil nil) +(832 "\"12345a\" =~ /(\\d+)(\\w)/" "(\\d+)(\\w)" nil nil nil nil "12345a" nil 1 0 "12345a" ("12345" "a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(833 "\"12345+\" =~ /(\\d+)(\\w)/" "(\\d+)(\\w)" nil nil nil nil "12345+" nil 1 0 "12345" ("1234" "5" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(834 "\"12345a\" =~ /((?>\\d+))(\\w)/" "((?>\\d+))(\\w)" nil nil nil nil "12345a" nil 1 0 "12345a" ("12345" "a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(835 "\"12345+\" =~ /((?>\\d+))(\\w)/" "((?>\\d+))(\\w)" nil nil nil nil "12345+" nil 1 0 nil nil) +(836 "\"aaab\" =~ /(?>a+)b/" "(?>a+)b" nil nil nil nil "aaab" nil 1 0 "aaab" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(837 "\"aaab\" =~ /((?>a+)b)/" "((?>a+)b)" nil nil nil nil "aaab" nil 1 0 "aaab" ("aaab" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(838 "\"aaab\" =~ /(?>(a+))b/" "(?>(a+))b" nil nil nil nil "aaab" nil 1 0 "aaab" ("aaa" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(839 "\"aaabbbccc\" =~ /(?>b)+/" "(?>b)+" nil nil nil nil "aaabbbccc" nil 1 0 "bbb" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(840 "\"aaabbbbccccd\" =~ /(?>a+|b+|c+)*c/" "(?>a+|b+|c+)*c" nil nil nil nil "aaabbbbccccd" nil 1 0 "aaabbbbc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(841 "\"((abc(ade)ufh()()x\" =~ /((?>[^()]+)|\\([^()]*\\))+/" "((?>[^()]+)|\\([^()]*\\))+" nil nil nil nil "((abc(ade)ufh()()x" nil 1 0 "abc(ade)ufh()()x" ("x" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(842 "\"(abc)\" =~ /\\(((?>[^()]+)|\\([^()]+\\))+\\)/" "\\(((?>[^()]+)|\\([^()]+\\))+\\)" nil nil nil nil "(abc)" nil 1 0 "(abc)" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(843 "\"(abc(def)xyz)\" =~ /\\(((?>[^()]+)|\\([^()]+\\))+\\)/" "\\(((?>[^()]+)|\\([^()]+\\))+\\)" nil nil nil nil "(abc(def)xyz)" nil 1 0 "(abc(def)xyz)" ("xyz" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(844 "\"((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\" =~ /\\(((?>[^()]+)|\\([^()]+\\))+\\)/" "\\(((?>[^()]+)|\\([^()]+\\))+\\)" nil nil nil nil "((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" nil 1 0 nil nil) +(845 "\"ab\" =~ /a(?-i)b/i" "a(?-i)b" t nil nil nil "ab" nil 1 0 "ab" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(846 "\"Ab\" =~ /a(?-i)b/i" "a(?-i)b" t nil nil nil "Ab" nil 1 0 "Ab" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(847 "\"aB\" =~ /a(?-i)b/i" "a(?-i)b" t nil nil nil "aB" nil 1 0 nil nil) +(848 "\"AB\" =~ /a(?-i)b/i" "a(?-i)b" t nil nil nil "AB" nil 1 0 nil nil) +(849 "\"a bcd e\" =~ /(a (?x)b c)d e/" "(a (?x)b c)d e" nil nil nil nil "a bcd e" nil 1 0 "a bcd e" ("a bc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(850 "\"a b cd e\" =~ /(a (?x)b c)d e/" "(a (?x)b c)d e" nil nil nil nil "a b cd e" nil 1 0 nil nil) +(851 "\"abcd e\" =~ /(a (?x)b c)d e/" "(a (?x)b c)d e" nil nil nil nil "abcd e" nil 1 0 nil nil) +(852 "\"a bcde\" =~ /(a (?x)b c)d e/" "(a (?x)b c)d e" nil nil nil nil "a bcde" nil 1 0 nil nil) +(853 "\"a bcde f\" =~ /(a b(?x)c d (?-x)e f)/" "(a b(?x)c d (?-x)e f)" nil nil nil nil "a bcde f" nil 1 0 "a bcde f" ("a bcde f" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(854 "\"abcdef\" =~ /(a b(?x)c d (?-x)e f)/" "(a b(?x)c d (?-x)e f)" nil nil nil nil "abcdef" nil 1 0 nil nil) +(855 "\"abc\" =~ /(a(?i)b)c/" "(a(?i)b)c" nil nil nil nil "abc" nil 1 0 "abc" ("ab" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(856 "\"aBc\" =~ /(a(?i)b)c/" "(a(?i)b)c" nil nil nil nil "aBc" nil 1 0 "aBc" ("aB" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(857 "\"abC\" =~ /(a(?i)b)c/" "(a(?i)b)c" nil nil nil nil "abC" nil 1 0 nil nil) +(858 "\"aBC\" =~ /(a(?i)b)c/" "(a(?i)b)c" nil nil nil nil "aBC" nil 1 0 nil nil) +(859 "\"Abc\" =~ /(a(?i)b)c/" "(a(?i)b)c" nil nil nil nil "Abc" nil 1 0 nil nil) +(860 "\"ABc\" =~ /(a(?i)b)c/" "(a(?i)b)c" nil nil nil nil "ABc" nil 1 0 nil nil) +(861 "\"ABC\" =~ /(a(?i)b)c/" "(a(?i)b)c" nil nil nil nil "ABC" nil 1 0 nil nil) +(862 "\"AbC\" =~ /(a(?i)b)c/" "(a(?i)b)c" nil nil nil nil "AbC" nil 1 0 nil nil) +(863 "\"abc\" =~ /a(?i:b)c/" "a(?i:b)c" nil nil nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(864 "\"aBc\" =~ /a(?i:b)c/" "a(?i:b)c" nil nil nil nil "aBc" nil 1 0 "aBc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(865 "\"ABC\" =~ /a(?i:b)c/" "a(?i:b)c" nil nil nil nil "ABC" nil 1 0 nil nil) +(866 "\"abC\" =~ /a(?i:b)c/" "a(?i:b)c" nil nil nil nil "abC" nil 1 0 nil nil) +(867 "\"aBC\" =~ /a(?i:b)c/" "a(?i:b)c" nil nil nil nil "aBC" nil 1 0 nil nil) +(868 "\"aBc\" =~ /a(?i:b)*c/" "a(?i:b)*c" nil nil nil nil "aBc" nil 1 0 "aBc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(869 "\"aBBc\" =~ /a(?i:b)*c/" "a(?i:b)*c" nil nil nil nil "aBBc" nil 1 0 "aBBc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(870 "\"aBC\" =~ /a(?i:b)*c/" "a(?i:b)*c" nil nil nil nil "aBC" nil 1 0 nil nil) +(871 "\"aBBC\" =~ /a(?i:b)*c/" "a(?i:b)*c" nil nil nil nil "aBBC" nil 1 0 nil nil) +(872 "\"abcd\" =~ /a(?=b(?i)c)\\w\\wd/" "a(?=b(?i)c)\\w\\wd" nil nil nil nil "abcd" nil 1 0 "abcd" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(873 "\"abCd\" =~ /a(?=b(?i)c)\\w\\wd/" "a(?=b(?i)c)\\w\\wd" nil nil nil nil "abCd" nil 1 0 "abCd" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(874 "\"aBCd\" =~ /a(?=b(?i)c)\\w\\wd/" "a(?=b(?i)c)\\w\\wd" nil nil nil nil "aBCd" nil 1 0 nil nil) +(875 "\"abcD\" =~ /a(?=b(?i)c)\\w\\wd/" "a(?=b(?i)c)\\w\\wd" nil nil nil nil "abcD" nil 1 0 nil nil) +(876 "\"more than million\" =~ /(?s-i:more.*than).*million/i" "(?s-i:more.*than).*million" t nil nil nil "more than million" nil 1 0 "more than million" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(877 "\"more than MILLION\" =~ /(?s-i:more.*than).*million/i" "(?s-i:more.*than).*million" t nil nil nil "more than MILLION" nil 1 0 "more than MILLION" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(878 "\"more \\n than Million\" =~ /(?s-i:more.*than).*million/i" "(?s-i:more.*than).*million" t nil nil nil "more + than Million" nil 1 0 "more + than Million" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(879 "\"MORE THAN MILLION\" =~ /(?s-i:more.*than).*million/i" "(?s-i:more.*than).*million" t nil nil nil "MORE THAN MILLION" nil 1 0 nil nil) +(880 "\"more \\n than \\n million\" =~ /(?s-i:more.*than).*million/i" "(?s-i:more.*than).*million" t nil nil nil "more + than + million" nil 1 0 nil nil) +(881 "\"more than million\" =~ /(?:(?s-i)more.*than).*million/i" "(?:(?s-i)more.*than).*million" t nil nil nil "more than million" nil 1 0 "more than million" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(882 "\"more than MILLION\" =~ /(?:(?s-i)more.*than).*million/i" "(?:(?s-i)more.*than).*million" t nil nil nil "more than MILLION" nil 1 0 "more than MILLION" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(883 "\"more \\n than Million\" =~ /(?:(?s-i)more.*than).*million/i" "(?:(?s-i)more.*than).*million" t nil nil nil "more + than Million" nil 1 0 "more + than Million" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(884 "\"MORE THAN MILLION\" =~ /(?:(?s-i)more.*than).*million/i" "(?:(?s-i)more.*than).*million" t nil nil nil "MORE THAN MILLION" nil 1 0 nil nil) +(885 "\"more \\n than \\n million\" =~ /(?:(?s-i)more.*than).*million/i" "(?:(?s-i)more.*than).*million" t nil nil nil "more + than + million" nil 1 0 nil nil) +(886 "\"abc\" =~ /(?>a(?i)b+)+c/" "(?>a(?i)b+)+c" nil nil nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(887 "\"aBbc\" =~ /(?>a(?i)b+)+c/" "(?>a(?i)b+)+c" nil nil nil nil "aBbc" nil 1 0 "aBbc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(888 "\"aBBc\" =~ /(?>a(?i)b+)+c/" "(?>a(?i)b+)+c" nil nil nil nil "aBBc" nil 1 0 "aBBc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(889 "\"Abc\" =~ /(?>a(?i)b+)+c/" "(?>a(?i)b+)+c" nil nil nil nil "Abc" nil 1 0 nil nil) +(890 "\"abAb\" =~ /(?>a(?i)b+)+c/" "(?>a(?i)b+)+c" nil nil nil nil "abAb" nil 1 0 nil nil) +(891 "\"abbC\" =~ /(?>a(?i)b+)+c/" "(?>a(?i)b+)+c" nil nil nil nil "abbC" nil 1 0 nil nil) +(892 "\"abc\" =~ /(?=a(?i)b)\\w\\wc/" "(?=a(?i)b)\\w\\wc" nil nil nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(893 "\"aBc\" =~ /(?=a(?i)b)\\w\\wc/" "(?=a(?i)b)\\w\\wc" nil nil nil nil "aBc" nil 1 0 "aBc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(894 "\"Ab\" =~ /(?=a(?i)b)\\w\\wc/" "(?=a(?i)b)\\w\\wc" nil nil nil nil "Ab" nil 1 0 nil nil) +(895 "\"abC\" =~ /(?=a(?i)b)\\w\\wc/" "(?=a(?i)b)\\w\\wc" nil nil nil nil "abC" nil 1 0 nil nil) +(896 "\"aBC\" =~ /(?=a(?i)b)\\w\\wc/" "(?=a(?i)b)\\w\\wc" nil nil nil nil "aBC" nil 1 0 nil nil) +(897 "\"abxxc\" =~ /(?<=a(?i)b)(\\w\\w)c/" "(?<=a(?i)b)(\\w\\w)c" nil nil nil nil "abxxc" nil 1 0 "xxc" ("xx" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(898 "\"aBxxc\" =~ /(?<=a(?i)b)(\\w\\w)c/" "(?<=a(?i)b)(\\w\\w)c" nil nil nil nil "aBxxc" nil 1 0 "xxc" ("xx" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(899 "\"Abxxc\" =~ /(?<=a(?i)b)(\\w\\w)c/" "(?<=a(?i)b)(\\w\\w)c" nil nil nil nil "Abxxc" nil 1 0 nil nil) +(900 "\"ABxxc\" =~ /(?<=a(?i)b)(\\w\\w)c/" "(?<=a(?i)b)(\\w\\w)c" nil nil nil nil "ABxxc" nil 1 0 nil nil) +(901 "\"abxxC\" =~ /(?<=a(?i)b)(\\w\\w)c/" "(?<=a(?i)b)(\\w\\w)c" nil nil nil nil "abxxC" nil 1 0 nil nil) +(902 "\"aA\" =~ /(?:(a)|b)(?(1)A|B)/" "(?:(a)|b)(?(1)A|B)" nil nil nil nil "aA" nil 1 0 "aA" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(903 "\"bB\" =~ /(?:(a)|b)(?(1)A|B)/" "(?:(a)|b)(?(1)A|B)" nil nil nil nil "bB" nil 1 0 "bB" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(904 "\"aB\" =~ /(?:(a)|b)(?(1)A|B)/" "(?:(a)|b)(?(1)A|B)" nil nil nil nil "aB" nil 1 0 nil nil) +(905 "\"bA\" =~ /(?:(a)|b)(?(1)A|B)/" "(?:(a)|b)(?(1)A|B)" nil nil nil nil "bA" nil 1 0 nil nil) +(906 "\"aa\" =~ /^(a)?(?(1)a|b)+$/" "^(a)?(?(1)a|b)+$" nil nil nil nil "aa" nil 1 0 "aa" ("a" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(907 "\"b\" =~ /^(a)?(?(1)a|b)+$/" "^(a)?(?(1)a|b)+$" nil nil nil nil "b" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(908 "\"bb\" =~ /^(a)?(?(1)a|b)+$/" "^(a)?(?(1)a|b)+$" nil nil nil nil "bb" nil 1 0 "bb" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(909 "\"ab\" =~ /^(a)?(?(1)a|b)+$/" "^(a)?(?(1)a|b)+$" nil nil nil nil "ab" nil 1 0 nil nil) +(910 "\"abc:\" =~ /^(?(?=abc)\\w{3}:|\\d\\d)$/" "^(?(?=abc)\\w{3}:|\\d\\d)$" nil nil nil nil "abc:" nil 1 0 "abc:" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(911 "\"12\" =~ /^(?(?=abc)\\w{3}:|\\d\\d)$/" "^(?(?=abc)\\w{3}:|\\d\\d)$" nil nil nil nil "12" nil 1 0 "12" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(912 "\"123\" =~ /^(?(?=abc)\\w{3}:|\\d\\d)$/" "^(?(?=abc)\\w{3}:|\\d\\d)$" nil nil nil nil "123" nil 1 0 nil nil) +(913 "\"xyz\" =~ /^(?(?=abc)\\w{3}:|\\d\\d)$/" "^(?(?=abc)\\w{3}:|\\d\\d)$" nil nil nil nil "xyz" nil 1 0 nil nil) +(914 "\"abc:\" =~ /^(?(?!abc)\\d\\d|\\w{3}:)$/" "^(?(?!abc)\\d\\d|\\w{3}:)$" nil nil nil nil "abc:" nil 1 0 "abc:" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(915 "\"12\" =~ /^(?(?!abc)\\d\\d|\\w{3}:)$/" "^(?(?!abc)\\d\\d|\\w{3}:)$" nil nil nil nil "12" nil 1 0 "12" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(916 "\"123\" =~ /^(?(?!abc)\\d\\d|\\w{3}:)$/" "^(?(?!abc)\\d\\d|\\w{3}:)$" nil nil nil nil "123" nil 1 0 nil nil) +(917 "\"xyz\" =~ /^(?(?!abc)\\d\\d|\\w{3}:)$/" "^(?(?!abc)\\d\\d|\\w{3}:)$" nil nil nil nil "xyz" nil 1 0 nil nil) +(918 "\"foobar\" =~ /(?(?<=foo)bar|cat)/" "(?(?<=foo)bar|cat)" nil nil nil nil "foobar" nil 1 0 "bar" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(919 "\"cat\" =~ /(?(?<=foo)bar|cat)/" "(?(?<=foo)bar|cat)" nil nil nil nil "cat" nil 1 0 "cat" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(920 "\"fcat\" =~ /(?(?<=foo)bar|cat)/" "(?(?<=foo)bar|cat)" nil nil nil nil "fcat" nil 1 0 "cat" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(921 "\"focat\" =~ /(?(?<=foo)bar|cat)/" "(?(?<=foo)bar|cat)" nil nil nil nil "focat" nil 1 0 "cat" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(922 "\"foocat\" =~ /(?(?<=foo)bar|cat)/" "(?(?<=foo)bar|cat)" nil nil nil nil "foocat" nil 1 0 nil nil) +(923 "\"foobar\" =~ /(?(?a*)*/" "(?>a*)*" nil nil nil nil "a" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(955 "\"aa\" =~ /(?>a*)*/" "(?>a*)*" nil nil nil nil "aa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(956 "\"aaaa\" =~ /(?>a*)*/" "(?>a*)*" nil nil nil nil "aaaa" nil 1 0 "aaaa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(957 "\"abc\" =~ /(abc|)+/" "(abc|)+" nil nil nil nil "abc" nil 1 0 "abc" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(958 "\"abcabc\" =~ /(abc|)+/" "(abc|)+" nil nil nil nil "abcabc" nil 1 0 "abcabc" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(959 "\"abcabcabc\" =~ /(abc|)+/" "(abc|)+" nil nil nil nil "abcabcabc" nil 1 0 "abcabcabc" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(960 "\"xyz\" =~ /(abc|)+/" "(abc|)+" nil nil nil nil "xyz" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(961 "\"a\" =~ /([a]*)*/" "([a]*)*" nil nil nil nil "a" nil 1 0 "a" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(962 "\"aaaaa\" =~ /([a]*)*/" "([a]*)*" nil nil nil nil "aaaaa" nil 1 0 "aaaaa" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(963 "\"a\" =~ /([ab]*)*/" "([ab]*)*" nil nil nil nil "a" nil 1 0 "a" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(964 "\"b\" =~ /([ab]*)*/" "([ab]*)*" nil nil nil nil "b" nil 1 0 "b" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(965 "\"ababab\" =~ /([ab]*)*/" "([ab]*)*" nil nil nil nil "ababab" nil 1 0 "ababab" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(966 "\"aaaabcde\" =~ /([ab]*)*/" "([ab]*)*" nil nil nil nil "aaaabcde" nil 1 0 "aaaab" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(967 "\"bbbb\" =~ /([ab]*)*/" "([ab]*)*" nil nil nil nil "bbbb" nil 1 0 "bbbb" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(968 "\"b\" =~ /([^a]*)*/" "([^a]*)*" nil nil nil nil "b" nil 1 0 "b" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(969 "\"bbbb\" =~ /([^a]*)*/" "([^a]*)*" nil nil nil nil "bbbb" nil 1 0 "bbbb" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(970 "\"aaa\" =~ /([^a]*)*/" "([^a]*)*" nil nil nil nil "aaa" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(971 "\"cccc\" =~ /([^ab]*)*/" "([^ab]*)*" nil nil nil nil "cccc" nil 1 0 "cccc" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(972 "\"abab\" =~ /([^ab]*)*/" "([^ab]*)*" nil nil nil nil "abab" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(973 "\"a\" =~ /([a]*?)*/" "([a]*?)*" nil nil nil nil "a" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(974 "\"aaaa\" =~ /([a]*?)*/" "([a]*?)*" nil nil nil nil "aaaa" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(975 "\"a\" =~ /([ab]*?)*/" "([ab]*?)*" nil nil nil nil "a" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(976 "\"b\" =~ /([ab]*?)*/" "([ab]*?)*" nil nil nil nil "b" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(977 "\"abab\" =~ /([ab]*?)*/" "([ab]*?)*" nil nil nil nil "abab" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(978 "\"baba\" =~ /([ab]*?)*/" "([ab]*?)*" nil nil nil nil "baba" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(979 "\"b\" =~ /([^a]*?)*/" "([^a]*?)*" nil nil nil nil "b" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(980 "\"bbbb\" =~ /([^a]*?)*/" "([^a]*?)*" nil nil nil nil "bbbb" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(981 "\"aaa\" =~ /([^a]*?)*/" "([^a]*?)*" nil nil nil nil "aaa" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(982 "\"c\" =~ /([^ab]*?)*/" "([^ab]*?)*" nil nil nil nil "c" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(983 "\"cccc\" =~ /([^ab]*?)*/" "([^ab]*?)*" nil nil nil nil "cccc" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(984 "\"baba\" =~ /([^ab]*?)*/" "([^ab]*?)*" nil nil nil nil "baba" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(985 "\"a\" =~ /(?>a*)*/" "(?>a*)*" nil nil nil nil "a" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(986 "\"aaabcde\" =~ /(?>a*)*/" "(?>a*)*" nil nil nil nil "aaabcde" nil 1 0 "aaa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(987 "\"aaaaa\" =~ /((?>a*))*/" "((?>a*))*" nil nil nil nil "aaaaa" nil 1 0 "aaaaa" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(988 "\"aabbaa\" =~ /((?>a*))*/" "((?>a*))*" nil nil nil nil "aabbaa" nil 1 0 "aa" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(989 "\"aaaaa\" =~ /((?>a*?))*/" "((?>a*?))*" nil nil nil nil "aaaaa" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(990 "\"aabbaa\" =~ /((?>a*?))*/" "((?>a*?))*" nil nil nil nil "aabbaa" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(991 "\"12-sep-98\" =~ /(?(?=[^a-z]+[a-z]) \\d{2}-[a-z]{3}-\\d{2} | \\d{2}-\\d{2}-\\d{2} ) /x" "(?(?=[^a-z]+[a-z]) \\d{2}-[a-z]{3}-\\d{2} | \\d{2}-\\d{2}-\\d{2} ) " nil nil nil t "12-sep-98" nil 1 0 "12-sep-98" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(992 "\"12-09-98\" =~ /(?(?=[^a-z]+[a-z]) \\d{2}-[a-z]{3}-\\d{2} | \\d{2}-\\d{2}-\\d{2} ) /x" "(?(?=[^a-z]+[a-z]) \\d{2}-[a-z]{3}-\\d{2} | \\d{2}-\\d{2}-\\d{2} ) " nil nil nil t "12-09-98" nil 1 0 "12-09-98" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(993 "\"sep-12-98\" =~ /(?(?=[^a-z]+[a-z]) \\d{2}-[a-z]{3}-\\d{2} | \\d{2}-\\d{2}-\\d{2} ) /x" "(?(?=[^a-z]+[a-z]) \\d{2}-[a-z]{3}-\\d{2} | \\d{2}-\\d{2}-\\d{2} ) " nil nil nil t "sep-12-98" nil 1 0 nil nil) +(994 "\"foobarfoo\" =~ /(?<=(foo))bar\\1/" "(?<=(foo))bar\\1" nil nil nil nil "foobarfoo" nil 1 0 "barfoo" ("foo" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(995 "\"foobarfootling\" =~ /(?<=(foo))bar\\1/" "(?<=(foo))bar\\1" nil nil nil nil "foobarfootling" nil 1 0 "barfoo" ("foo" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(996 "\"foobar\" =~ /(?<=(foo))bar\\1/" "(?<=(foo))bar\\1" nil nil nil nil "foobar" nil 1 0 nil nil) +(997 "\"barfoo\" =~ /(?<=(foo))bar\\1/" "(?<=(foo))bar\\1" nil nil nil nil "barfoo" nil 1 0 nil nil) +(998 "\"saturday\" =~ /(?i:saturday|sunday)/" "(?i:saturday|sunday)" nil nil nil nil "saturday" nil 1 0 "saturday" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(999 "\"sunday\" =~ /(?i:saturday|sunday)/" "(?i:saturday|sunday)" nil nil nil nil "sunday" nil 1 0 "sunday" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1000 "\"Saturday\" =~ /(?i:saturday|sunday)/" "(?i:saturday|sunday)" nil nil nil nil "Saturday" nil 1 0 "Saturday" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1001 "\"Sunday\" =~ /(?i:saturday|sunday)/" "(?i:saturday|sunday)" nil nil nil nil "Sunday" nil 1 0 "Sunday" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1002 "\"SATURDAY\" =~ /(?i:saturday|sunday)/" "(?i:saturday|sunday)" nil nil nil nil "SATURDAY" nil 1 0 "SATURDAY" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1003 "\"SUNDAY\" =~ /(?i:saturday|sunday)/" "(?i:saturday|sunday)" nil nil nil nil "SUNDAY" nil 1 0 "SUNDAY" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1004 "\"SunDay\" =~ /(?i:saturday|sunday)/" "(?i:saturday|sunday)" nil nil nil nil "SunDay" nil 1 0 "SunDay" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1005 "\"abcx\" =~ /(a(?i)bc|BB)x/" "(a(?i)bc|BB)x" nil nil nil nil "abcx" nil 1 0 "abcx" ("abc" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1006 "\"aBCx\" =~ /(a(?i)bc|BB)x/" "(a(?i)bc|BB)x" nil nil nil nil "aBCx" nil 1 0 "aBCx" ("aBC" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1007 "\"bbx\" =~ /(a(?i)bc|BB)x/" "(a(?i)bc|BB)x" nil nil nil nil "bbx" nil 1 0 "bbx" ("bb" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1008 "\"BBx\" =~ /(a(?i)bc|BB)x/" "(a(?i)bc|BB)x" nil nil nil nil "BBx" nil 1 0 "BBx" ("BB" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1009 "\"abcX\" =~ /(a(?i)bc|BB)x/" "(a(?i)bc|BB)x" nil nil nil nil "abcX" nil 1 0 nil nil) +(1010 "\"aBCX\" =~ /(a(?i)bc|BB)x/" "(a(?i)bc|BB)x" nil nil nil nil "aBCX" nil 1 0 nil nil) +(1011 "\"bbX\" =~ /(a(?i)bc|BB)x/" "(a(?i)bc|BB)x" nil nil nil nil "bbX" nil 1 0 nil nil) +(1012 "\"BBX\" =~ /(a(?i)bc|BB)x/" "(a(?i)bc|BB)x" nil nil nil nil "BBX" nil 1 0 nil nil) +(1013 "\"ac\" =~ /^([ab](?i)[cd]|[ef])/" "^([ab](?i)[cd]|[ef])" nil nil nil nil "ac" nil 1 0 "ac" ("ac" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1014 "\"aC\" =~ /^([ab](?i)[cd]|[ef])/" "^([ab](?i)[cd]|[ef])" nil nil nil nil "aC" nil 1 0 "aC" ("aC" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1015 "\"bD\" =~ /^([ab](?i)[cd]|[ef])/" "^([ab](?i)[cd]|[ef])" nil nil nil nil "bD" nil 1 0 "bD" ("bD" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1016 "\"elephant\" =~ /^([ab](?i)[cd]|[ef])/" "^([ab](?i)[cd]|[ef])" nil nil nil nil "elephant" nil 1 0 "e" ("e" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1017 "\"Europe\" =~ /^([ab](?i)[cd]|[ef])/" "^([ab](?i)[cd]|[ef])" nil nil nil nil "Europe" nil 1 0 "E" ("E" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1018 "\"frog\" =~ /^([ab](?i)[cd]|[ef])/" "^([ab](?i)[cd]|[ef])" nil nil nil nil "frog" nil 1 0 "f" ("f" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1019 "\"France\" =~ /^([ab](?i)[cd]|[ef])/" "^([ab](?i)[cd]|[ef])" nil nil nil nil "France" nil 1 0 "F" ("F" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1020 "\"Africa\" =~ /^([ab](?i)[cd]|[ef])/" "^([ab](?i)[cd]|[ef])" nil nil nil nil "Africa" nil 1 0 nil nil) +(1021 "\"ab\" =~ /^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/" "^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)" nil nil nil nil "ab" nil 1 0 "ab" ("ab" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1022 "\"aBd\" =~ /^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/" "^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)" nil nil nil nil "aBd" nil 1 0 "aBd" ("aBd" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1023 "\"xy\" =~ /^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/" "^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)" nil nil nil nil "xy" nil 1 0 "xy" ("xy" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1024 "\"xY\" =~ /^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/" "^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)" nil nil nil nil "xY" nil 1 0 "xY" ("xY" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1025 "\"zebra\" =~ /^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/" "^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)" nil nil nil nil "zebra" nil 1 0 "z" ("z" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1026 "\"Zambesi\" =~ /^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/" "^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)" nil nil nil nil "Zambesi" nil 1 0 "Z" ("Z" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1027 "\"aCD\" =~ /^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/" "^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)" nil nil nil nil "aCD" nil 1 0 nil nil) +(1028 "\"XY\" =~ /^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/" "^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)" nil nil nil nil "XY" nil 1 0 nil nil) +(1029 "\"foo\\nbar\" =~ /(?<=foo\\n)^bar/m" "(?<=foo\\n)^bar" nil t nil nil "foo +bar" nil 1 0 "bar" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1030 "\"bar\" =~ /(?<=foo\\n)^bar/m" "(?<=foo\\n)^bar" nil t nil nil "bar" nil 1 0 nil nil) +(1031 "\"baz\\nbar\" =~ /(?<=foo\\n)^bar/m" "(?<=foo\\n)^bar" nil t nil nil "baz +bar" nil 1 0 nil nil) +(1032 "\"barbaz\" =~ /(?<=(?]&/" "^[<>]&" nil nil nil nil "<&OUT" nil 1 0 "<&" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1369 "\"aaaaaaaaaa\" =~ /^(a\\1?){4}$/" "^(a\\1?){4}$" nil nil nil nil "aaaaaaaaaa" nil 1 0 "aaaaaaaaaa" ("aaaa" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1370 "\"AB\" =~ /^(a\\1?){4}$/" "^(a\\1?){4}$" nil nil nil nil "AB" nil 1 0 nil nil) +(1371 "\"aaaaaaaaa\" =~ /^(a\\1?){4}$/" "^(a\\1?){4}$" nil nil nil nil "aaaaaaaaa" nil 1 0 nil nil) +(1372 "\"aaaaaaaaaaa\" =~ /^(a\\1?){4}$/" "^(a\\1?){4}$" nil nil nil nil "aaaaaaaaaaa" nil 1 0 nil nil) +(1373 "\"aaaaaaaaaa\" =~ /^(a(?(1)\\1)){4}$/" "^(a(?(1)\\1)){4}$" nil nil nil nil "aaaaaaaaaa" nil 1 0 "aaaaaaaaaa" ("aaaa" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1374 "\"aaaaaaaaa\" =~ /^(a(?(1)\\1)){4}$/" "^(a(?(1)\\1)){4}$" nil nil nil nil "aaaaaaaaa" nil 1 0 nil nil) +(1375 "\"aaaaaaaaaaa\" =~ /^(a(?(1)\\1)){4}$/" "^(a(?(1)\\1)){4}$" nil nil nil nil "aaaaaaaaaaa" nil 1 0 nil nil) +(1376 "\"foobar\" =~ /(?:(f)(o)(o)|(b)(a)(r))*/" "(?:(f)(o)(o)|(b)(a)(r))*" nil nil nil nil "foobar" nil 1 0 "foobar" ("f" "o" "o" "b" "a" "r" nil nil nil nil nil nil nil nil nil nil)) +(1377 "\"ab\" =~ /(?<=a)b/" "(?<=a)b" nil nil nil nil "ab" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1378 "\"cb\" =~ /(?<=a)b/" "(?<=a)b" nil nil nil nil "cb" nil 1 0 nil nil) +(1379 "\"b\" =~ /(?<=a)b/" "(?<=a)b" nil nil nil nil "b" nil 1 0 nil nil) +(1380 "\"ab\" =~ /(?a+)b/" "(?>a+)b" nil nil nil nil "aaab" nil 1 0 "aaab" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1491 "\"a:[b]:\" =~ /([[:]+)/" "([[:]+)" nil nil nil nil "a:[b]:" nil 1 0 ":[" (":[" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1492 "\"a=[b]=\" =~ /([[=]+)/" "([[=]+)" nil nil nil nil "a=[b]=" nil 1 0 "=[" ("=[" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1493 "\"a.[b].\" =~ /([[.]+)/" "([[.]+)" nil nil nil nil "a.[b]." nil 1 0 ".[" (".[" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1494 "\"aaab\" =~ /((?>a+)b)/" "((?>a+)b)" nil nil nil nil "aaab" nil 1 0 "aaab" ("aaab" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1495 "\"aaab\" =~ /(?>(a+))b/" "(?>(a+))b" nil nil nil nil "aaab" nil 1 0 "aaab" ("aaa" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1496 "\"((abc(ade)ufh()()x\" =~ /((?>[^()]+)|\\([^()]*\\))+/" "((?>[^()]+)|\\([^()]*\\))+" nil nil nil nil "((abc(ade)ufh()()x" nil 1 0 "abc(ade)ufh()()x" ("x" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1497 "\"aaab\" =~ /a\\Z/" "a\\Z" nil nil nil nil "aaab" nil 1 0 nil nil) +(1498 "\"a\\nb\\n\" =~ /a\\Z/" "a\\Z" nil nil nil nil "a +b +" nil 1 0 nil nil) +(1499 "\"a\\nb\\n\" =~ /b\\Z/" "b\\Z" nil nil nil nil "a +b +" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1500 "\"a\\nb\" =~ /b\\Z/" "b\\Z" nil nil nil nil "a +b" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1501 "\"a\\nb\" =~ /b\\z/" "b\\z" nil nil nil nil "a +b" nil 1 0 "b" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1502 "\"a\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "a" nil 1 0 "a" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1503 "\"abc\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "abc" nil 1 0 "abc" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1504 "\"a-b\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "a-b" nil 1 0 "a-b" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1505 "\"0-9\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "0-9" nil 1 0 "0-9" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1506 "\"a.b\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "a.b" nil 1 0 "a.b" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1507 "\"5.6.7\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "5.6.7" nil 1 0 "5.6.7" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1508 "\"the.quick.brown.fox\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "the.quick.brown.fox" nil 1 0 "the.quick.brown.fox" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1509 "\"a100.b200.300c\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "a100.b200.300c" nil 1 0 "a100.b200.300c" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1510 "\"12-ab.1245\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "12-ab.1245" nil 1 0 "12-ab.1245" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1511 "\"\\\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "" nil 1 0 nil nil) +(1512 "\".a\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil ".a" nil 1 0 nil nil) +(1513 "\"-a\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "-a" nil 1 0 nil nil) +(1514 "\"a-\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "a-" nil 1 0 nil nil) +(1515 "\"a.\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "a." nil 1 0 nil nil) +(1516 "\"a_b\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "a_b" nil 1 0 nil nil) +(1517 "\"a.-\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "a.-" nil 1 0 nil nil) +(1518 "\"a..\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "a.." nil 1 0 nil nil) +(1519 "\"ab..bc\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "ab..bc" nil 1 0 nil nil) +(1520 "\"the.quick.brown.fox-\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "the.quick.brown.fox-" nil 1 0 nil nil) +(1521 "\"the.quick.brown.fox.\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "the.quick.brown.fox." nil 1 0 nil nil) +(1522 "\"the.quick.brown.fox_\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "the.quick.brown.fox_" nil 1 0 nil nil) +(1523 "\"the.quick.brown.fox+\" =~ /^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$/" "^(?>(?(1)\\.|())[^\\W_](?>[a-z0-9-]*[^\\W_])?)+$" nil nil nil nil "the.quick.brown.fox+" nil 1 0 nil nil) +(1524 "\"alphabetabcd\" =~ /(?>.*)(?<=(abcd|wxyz))/" "(?>.*)(?<=(abcd|wxyz))" nil nil nil nil "alphabetabcd" nil 1 0 "alphabetabcd" ("abcd" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1525 "\"endingwxyz\" =~ /(?>.*)(?<=(abcd|wxyz))/" "(?>.*)(?<=(abcd|wxyz))" nil nil nil nil "endingwxyz" nil 1 0 "endingwxyz" ("wxyz" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1526 "\"a rather long string that doesn't end with one of them\" =~ /(?>.*)(?<=(abcd|wxyz))/" "(?>.*)(?<=(abcd|wxyz))" nil nil nil nil "a rather long string that doesn't end with one of them" nil 1 0 nil nil) +(1527 "\"word cat dog elephant mussel cow horse canary baboon snake shark otherword\" =~ /word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword/" "word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword" nil nil nil nil "word cat dog elephant mussel cow horse canary baboon snake shark otherword" nil 1 0 "word cat dog elephant mussel cow horse canary baboon snake shark otherword" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1528 "\"word cat dog elephant mussel cow horse canary baboon snake shark\" =~ /word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword/" "word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword" nil nil nil nil "word cat dog elephant mussel cow horse canary baboon snake shark" nil 1 0 nil nil) +(1529 "\"word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope\" =~ /word (?>[a-zA-Z0-9]+ ){0,30}otherword/" "word (?>[a-zA-Z0-9]+ ){0,30}otherword" nil nil nil nil "word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope" nil 1 0 nil nil) +(1530 "\"999foo\" =~ /(?<=\\d{3}(?!999))foo/" "(?<=\\d{3}(?!999))foo" nil nil nil nil "999foo" nil 1 0 "foo" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1531 "\"123999foo\" =~ /(?<=\\d{3}(?!999))foo/" "(?<=\\d{3}(?!999))foo" nil nil nil nil "123999foo" nil 1 0 "foo" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1532 "\"123abcfoo\" =~ /(?<=\\d{3}(?!999))foo/" "(?<=\\d{3}(?!999))foo" nil nil nil nil "123abcfoo" nil 1 0 nil nil) +(1533 "\"999foo\" =~ /(?<=(?!...999)\\d{3})foo/" "(?<=(?!...999)\\d{3})foo" nil nil nil nil "999foo" nil 1 0 "foo" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1534 "\"123999foo\" =~ /(?<=(?!...999)\\d{3})foo/" "(?<=(?!...999)\\d{3})foo" nil nil nil nil "123999foo" nil 1 0 "foo" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1535 "\"123abcfoo\" =~ /(?<=(?!...999)\\d{3})foo/" "(?<=(?!...999)\\d{3})foo" nil nil nil nil "123abcfoo" nil 1 0 nil nil) +(1536 "\"123abcfoo\" =~ /(?<=\\d{3}(?!999)...)foo/" "(?<=\\d{3}(?!999)...)foo" nil nil nil nil "123abcfoo" nil 1 0 "foo" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1537 "\"123456foo\" =~ /(?<=\\d{3}(?!999)...)foo/" "(?<=\\d{3}(?!999)...)foo" nil nil nil nil "123456foo" nil 1 0 "foo" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1538 "\"123999foo\" =~ /(?<=\\d{3}(?!999)...)foo/" "(?<=\\d{3}(?!999)...)foo" nil nil nil nil "123999foo" nil 1 0 nil nil) +(1539 "\"123abcfoo\" =~ /(?<=\\d{3}...)(?\\s*)=(?>\\s*) # find
\\s*)=(?>\\s*) # find \\s*)=(?>\\s*) # find \\s*)=(?>\\s*) # find \\s*)=(?>\\s*) # find \\s*)=(?>\\s*) # find Z)+|A)*/" "((?>Z)+|A)*" nil nil nil nil "ZABCDEFG" nil 1 0 "ZA" ("A" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1555 "\"ZABCDEFG\" =~ /((?>)+|A)*/" "((?>)+|A)*" nil nil nil nil "ZABCDEFG" nil 1 0 "" ("" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1556 "\"abbab\" =~ /a*/" "a*" nil nil nil nil "abbab" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1557 "\"abcde\" =~ /^[a-\\d]/" "^[a-\\d]" nil nil nil nil "abcde" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1558 "\"-things\" =~ /^[a-\\d]/" "^[a-\\d]" nil nil nil nil "-things" nil 1 0 "-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1559 "\"0digit\" =~ /^[a-\\d]/" "^[a-\\d]" nil nil nil nil "0digit" nil 1 0 "0" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1560 "\"bcdef\" =~ /^[a-\\d]/" "^[a-\\d]" nil nil nil nil "bcdef" nil 1 0 nil nil) +(1561 "\"abcde\" =~ /^[\\d-a]/" "^[\\d-a]" nil nil nil nil "abcde" nil 1 0 "a" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1562 "\"-things\" =~ /^[\\d-a]/" "^[\\d-a]" nil nil nil nil "-things" nil 1 0 "-" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1563 "\"0digit\" =~ /^[\\d-a]/" "^[\\d-a]" nil nil nil nil "0digit" nil 1 0 "0" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1564 "\"bcdef\" =~ /^[\\d-a]/" "^[\\d-a]" nil nil nil nil "bcdef" nil 1 0 nil nil) +(1565 "\"abcdef\" =~ /(?<=abc).*(?=def)/" "(?<=abc).*(?=def)" nil nil nil nil "abcdef" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1566 "\"abcxdef\" =~ /(?<=abc).*(?=def)/" "(?<=abc).*(?=def)" nil nil nil nil "abcxdef" nil 1 0 "x" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1567 "\"abcxdefxdef\" =~ /(?<=abc).*(?=def)/" "(?<=abc).*(?=def)" nil nil nil nil "abcxdefxdef" nil 1 0 "xdefx" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1568 "\"abcdef\" =~ /(?<=abc).*?(?=def)/" "(?<=abc).*?(?=def)" nil nil nil nil "abcdef" nil 1 0 "" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1569 "\"abcxdef\" =~ /(?<=abc).*?(?=def)/" "(?<=abc).*?(?=def)" nil nil nil nil "abcxdef" nil 1 0 "x" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1570 "\"abcxdefxdef\" =~ /(?<=abc).*?(?=def)/" "(?<=abc).*?(?=def)" nil nil nil nil "abcxdefxdef" nil 1 0 "x" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1571 "\"abcdef\" =~ /(?<=abc).+(?=def)/" "(?<=abc).+(?=def)" nil nil nil nil "abcdef" nil 1 0 nil nil) +(1572 "\"abcxdef\" =~ /(?<=abc).+(?=def)/" "(?<=abc).+(?=def)" nil nil nil nil "abcxdef" nil 1 0 "x" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1573 "\"abcxdefxdef\" =~ /(?<=abc).+(?=def)/" "(?<=abc).+(?=def)" nil nil nil nil "abcxdefxdef" nil 1 0 "xdefx" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1574 "\"abcdef\" =~ /(?<=abc).+?(?=def)/" "(?<=abc).+?(?=def)" nil nil nil nil "abcdef" nil 1 0 nil nil) +(1575 "\"abcxdef\" =~ /(?<=abc).+?(?=def)/" "(?<=abc).+?(?=def)" nil nil nil nil "abcxdef" nil 1 0 "x" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1576 "\"abcxdefxdef\" =~ /(?<=abc).+?(?=def)/" "(?<=abc).+?(?=def)" nil nil nil nil "abcxdefxdef" nil 1 0 "x" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1577 "\"-abcdef\" =~ /(?<=\\b)(.*)/" "(?<=\\b)(.*)" nil nil nil nil "-abcdef" nil 1 0 "abcdef" ("abcdef" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1578 "\"abcdef\" =~ /(?<=\\b)(.*)/" "(?<=\\b)(.*)" nil nil nil nil "abcdef" nil 1 0 "abcdef" ("abcdef" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1579 "\"-abcdef\" =~ /(?<=\\B)(.*)/" "(?<=\\B)(.*)" nil nil nil nil "-abcdef" nil 1 0 "-abcdef" ("-abcdef" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1580 "\"abcdef\" =~ /(?<=\\B)(.*)/" "(?<=\\B)(.*)" nil nil nil nil "abcdef" nil 1 0 "bcdef" ("bcdef" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1581 "\"'a'\" =~ /^'[ab]'/" "^'[ab]'" nil nil nil nil "'a'" nil 1 0 "'a'" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1582 "\"'b'\" =~ /^'[ab]'/" "^'[ab]'" nil nil nil nil "'b'" nil 1 0 "'b'" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1583 "\"x'a'\" =~ /^'[ab]'/" "^'[ab]'" nil nil nil nil "x'a'" nil 1 0 nil nil) +(1584 "\"'a'x\" =~ /^'[ab]'/" "^'[ab]'" nil nil nil nil "'a'x" nil 1 0 "'a'" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1585 "\"'ab'\" =~ /^'[ab]'/" "^'[ab]'" nil nil nil nil "'ab'" nil 1 0 nil nil) +(1586 "\"'a'\" =~ /^'[ab]'$/" "^'[ab]'$" nil nil nil nil "'a'" nil 1 0 "'a'" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1587 "\"'b'\" =~ /^'[ab]'$/" "^'[ab]'$" nil nil nil nil "'b'" nil 1 0 "'b'" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1588 "\"x'a'\" =~ /^'[ab]'$/" "^'[ab]'$" nil nil nil nil "x'a'" nil 1 0 nil nil) +(1589 "\"'a'x\" =~ /^'[ab]'$/" "^'[ab]'$" nil nil nil nil "'a'x" nil 1 0 nil nil) +(1590 "\"'ab'\" =~ /^'[ab]'$/" "^'[ab]'$" nil nil nil nil "'ab'" nil 1 0 nil nil) +(1591 "\"'a'\" =~ /'[ab]'$/" "'[ab]'$" nil nil nil nil "'a'" nil 1 0 "'a'" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1592 "\"'b'\" =~ /'[ab]'$/" "'[ab]'$" nil nil nil nil "'b'" nil 1 0 "'b'" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1593 "\"x'a'\" =~ /'[ab]'$/" "'[ab]'$" nil nil nil nil "x'a'" nil 1 0 "'a'" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1594 "\"'a'x\" =~ /'[ab]'$/" "'[ab]'$" nil nil nil nil "'a'x" nil 1 0 nil nil) +(1595 "\"'ab'\" =~ /'[ab]'$/" "'[ab]'$" nil nil nil nil "'ab'" nil 1 0 nil nil) +(1596 "\"'a'\" =~ /'[ab]'/" "'[ab]'" nil nil nil nil "'a'" nil 1 0 "'a'" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1597 "\"'b'\" =~ /'[ab]'/" "'[ab]'" nil nil nil nil "'b'" nil 1 0 "'b'" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1598 "\"x'a'\" =~ /'[ab]'/" "'[ab]'" nil nil nil nil "x'a'" nil 1 0 "'a'" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1599 "\"'a'x\" =~ /'[ab]'/" "'[ab]'" nil nil nil nil "'a'x" nil 1 0 "'a'" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1600 "\"'ab'\" =~ /'[ab]'/" "'[ab]'" nil nil nil nil "'ab'" nil 1 0 nil nil) +(1601 "\"abc\" =~ /abc\\E/" "abc\\E" nil nil nil nil "abc" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1602 "\"abcE\" =~ /abc\\E/" "abc\\E" nil nil nil nil "abcE" nil 1 0 "abc" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1603 "\"abcx\" =~ /abc[\\Ex]/" "abc[\\Ex]" nil nil nil nil "abcx" nil 1 0 "abcx" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1604 "\"abcE\" =~ /abc[\\Ex]/" "abc[\\Ex]" nil nil nil nil "abcE" nil 1 0 nil nil) +(1605 "\"a*\" =~ /^\\Qa*\\E$/" "^\\Qa*\\E$" nil nil nil nil "a*" nil 1 0 "a*" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1606 "\"a\" =~ /^\\Qa*\\E$/" "^\\Qa*\\E$" nil nil nil nil "a" nil 1 0 nil nil) +(1607 "\"a*x\" =~ /\\Qa*x\\E/" "\\Qa*x\\E" nil nil nil nil "a*x" nil 1 0 "a*x" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1608 "\"a*\" =~ /\\Qa*x\\E/" "\\Qa*x\\E" nil nil nil nil "a*" nil 1 0 nil nil) +(1609 "\"a*x\" =~ /\\Qa*x/" "\\Qa*x" nil nil nil nil "a*x" nil 1 0 "a*x" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1610 "\"a*\" =~ /\\Qa*x/" "\\Qa*x" nil nil nil nil "a*" nil 1 0 nil nil) +(1611 "\"a*x\" =~ /\\Q\\Qa*x\\E\\E/" "\\Q\\Qa*x\\E\\E" nil nil nil nil "a*x" nil 1 0 nil nil) +(1612 "\"a\\\\*x\" =~ /\\Q\\Qa*x\\E\\E/" "\\Q\\Qa*x\\E\\E" nil nil nil nil "a\\*x" nil 1 0 "a\\*x" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1613 "\"a*x\" =~ /\\Q\\Qa*x\\E/" "\\Q\\Qa*x\\E" nil nil nil nil "a*x" nil 1 0 nil nil) +(1614 "\"a\\\\*x\" =~ /\\Q\\Qa*x\\E/" "\\Q\\Qa*x\\E" nil nil nil nil "a\\*x" nil 1 0 "a\\*x" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1615 "\"a[x]\" =~ /a\\Q[x\\E]/" "a\\Q[x\\E]" nil nil nil nil "a[x]" nil 1 0 "a[x]" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1616 "\"ax\" =~ /a\\Q[x\\E]/" "a\\Q[x\\E]" nil nil nil nil "ax" nil 1 0 nil nil) +(1617 "\"a\" =~ /a#comment\\Q... +{2}/x" "a#comment\\Q... +{2}" nil nil nil t "a" nil 1 0 nil nil) +(1618 "\"aa\" =~ /a#comment\\Q... +{2}/x" "a#comment\\Q... +{2}" nil nil nil t "aa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1619 "\"a\" =~ /a(?#comment\\Q... +){2}/x" "a(?#comment\\Q... +){2}" nil nil nil t "a" nil 1 0 nil nil) +(1620 "\"aa\" =~ /a(?#comment\\Q... +){2}/x" "a(?#comment\\Q... +){2}" nil nil nil t "aa" nil 1 0 "aa" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1621 "\"a.\" =~ /(?x)a#\\Q +./" "(?x)a#\\Q +." nil nil nil nil "a." nil 1 0 "a." (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1622 "\"aa\" =~ /(?x)a#\\Q +./" "(?x)a#\\Q +." nil nil nil nil "aa" nil 1 0 nil nil) +(1623 "\"abcdxklqj\" =~ /ab(?=.*q)cd/" "ab(?=.*q)cd" nil nil nil nil "abcdxklqj" nil 1 0 "abcd" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) +(1624 "\"ab\" =~ /a(?!.*$)b/" "a(?!.*$)b" nil nil nil nil "ab" nil 1 0 nil nil) +(1625 "\"Axi\" =~ /.{2}[a-z]/" ".{2}[a-z]" nil nil nil nil "Axi" nil 1 0 "Axi" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)) diff --git a/practicals/libraries/cl-ppcre-1.2.3/testinput b/practicals/libraries/cl-ppcre-1.2.3/testinput new file mode 100644 index 0000000..8f1ad56 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/testinput @@ -0,0 +1,3948 @@ +/the quick brown fox/ + the quick brown fox + The quick brown FOX + What do you know about the quick brown fox? + What do you know about THE QUICK BROWN FOX? + +/The quick brown fox/i + the quick brown fox + The quick brown FOX + What do you know about the quick brown fox? + What do you know about THE QUICK BROWN FOX? + +/abcd\t\n\r\f\a\e\071\x3b\$\\\?caxyz/ + abcd\t\n\r\f\a\e9;\$\\?caxyz + +/a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/ + abxyzpqrrrabbxyyyypqAzz + abxyzpqrrrabbxyyyypqAzz + aabxyzpqrrrabbxyyyypqAzz + aaabxyzpqrrrabbxyyyypqAzz + aaaabxyzpqrrrabbxyyyypqAzz + abcxyzpqrrrabbxyyyypqAzz + aabcxyzpqrrrabbxyyyypqAzz + aaabcxyzpqrrrabbxyyyypAzz + aaabcxyzpqrrrabbxyyyypqAzz + aaabcxyzpqrrrabbxyyyypqqAzz + aaabcxyzpqrrrabbxyyyypqqqAzz + aaabcxyzpqrrrabbxyyyypqqqqAzz + aaabcxyzpqrrrabbxyyyypqqqqqAzz + aaabcxyzpqrrrabbxyyyypqqqqqqAzz + aaaabcxyzpqrrrabbxyyyypqAzz + abxyzzpqrrrabbxyyyypqAzz + aabxyzzzpqrrrabbxyyyypqAzz + aaabxyzzzzpqrrrabbxyyyypqAzz + aaaabxyzzzzpqrrrabbxyyyypqAzz + abcxyzzpqrrrabbxyyyypqAzz + aabcxyzzzpqrrrabbxyyyypqAzz + aaabcxyzzzzpqrrrabbxyyyypqAzz + aaaabcxyzzzzpqrrrabbxyyyypqAzz + aaaabcxyzzzzpqrrrabbbxyyyypqAzz + aaaabcxyzzzzpqrrrabbbxyyyyypqAzz + aaabcxyzpqrrrabbxyyyypABzz + aaabcxyzpqrrrabbxyyyypABBzz + >>>aaabxyzpqrrrabbxyyyypqAzz + >aaaabxyzpqrrrabbxyyyypqAzz + >>>>abcxyzpqrrrabbxyyyypqAzz + abxyzpqrrabbxyyyypqAzz + abxyzpqrrrrabbxyyyypqAzz + abxyzpqrrrabxyyyypqAzz + aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz + aaaabcxyzzzzpqrrrabbbxyyypqAzz + aaabcxyzpqrrrabbxyyyypqqqqqqqAzz + +/^(abc){1,2}zz/ + abczz + abcabczz + zz + abcabcabczz + >>abczz + +/^(b+?|a){1,2}?c/ + bc + bbc + bbbc + bac + bbac + aac + abbbbbbbbbbbc + bbbbbbbbbbbac + aaac + abbbbbbbbbbbac + +/^(b+|a){1,2}c/ + bc + bbc + bbbc + bac + bbac + aac + abbbbbbbbbbbc + bbbbbbbbbbbac + aaac + abbbbbbbbbbbac + +/^(b+|a){1,2}?bc/ + bbc + +/^(b*|ba){1,2}?bc/ + babc + bbabc + bababc + bababbc + babababc + +/^(ba|b*){1,2}?bc/ + babc + bbabc + bababc + bababbc + babababc + +/^\ca\cA\c[\c{\c:/ + \x01\x01\e;z + +/^[ab\]cde]/ + athing + bthing + ]thing + cthing + dthing + ething + fthing + [thing + \\thing + +/^[]cde]/ + ]thing + cthing + dthing + ething + athing + fthing + +/^[^ab\]cde]/ + fthing + [thing + \\thing + athing + bthing + ]thing + cthing + dthing + ething + +/^[^]cde]/ + athing + fthing + ]thing + cthing + dthing + ething + +/^\/ + + +/^ÿ/ + ÿ + +/^[0-9]+$/ + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 100 + abc + +/^.*nter/ + enter + inter + uponter + +/^xxx[0-9]+$/ + xxx0 + xxx1234 + xxx + +/^.+[0-9][0-9][0-9]$/ + x123 + xx123 + 123456 + 123 + x1234 + +/^.+?[0-9][0-9][0-9]$/ + x123 + xx123 + 123456 + 123 + x1234 + +/^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/ + abc!pqr=apquxz.ixr.zzz.ac.uk + !pqr=apquxz.ixr.zzz.ac.uk + abc!=apquxz.ixr.zzz.ac.uk + abc!pqr=apquxz:ixr.zzz.ac.uk + abc!pqr=apquxz.ixr.zzz.ac.ukk + +/:/ + Well, we need a colon: somewhere + Fail if we don't + +/([\da-f:]+)$/i + 0abc + abc + fed + E + :: + 5f03:12C0::932e + fed def + Any old stuff + 0zzz + gzzz + fed\x20 + Any old rubbish + +/^.*\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ + .1.2.3 + A.12.123.0 + .1.2.3333 + 1.2.3 + 1234.2.3 + +/^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/ + 1 IN SOA non-sp1 non-sp2( + 1 IN SOA non-sp1 non-sp2 ( + 1IN SOA non-sp1 non-sp2( + +/^[a-zA-Z\d][a-zA-Z\d\-]*(\.[a-zA-Z\d][a-zA-z\d\-]*)*\.$/ + a. + Z. + 2. + ab-c.pq-r. + sxk.zzz.ac.uk. + x-.y-. + -abc.peq. + +/^\*\.[a-z]([a-z\-\d]*[a-z\d]+)?(\.[a-z]([a-z\-\d]*[a-z\d]+)?)*$/ + *.a + *.b0-a + *.c3-b.c + *.c-a.b-c + *.0 + *.a- + *.a-b.c- + *.c-a.0-c + +/^(?=ab(de))(abd)(e)/ + abde + +/^(?!(ab)de|x)(abd)(f)/ + abdf + +/^(?=(ab(cd)))(ab)/ + abcd + +/^[\da-f](\.[\da-f])*$/i + a.b.c.d + A.B.C.D + a.b.c.1.2.3.C + +/^\".*\"\s*(;.*)?$/ + \"1234\" + \"abcd\" ; + \"\" ; rhubarb + \"1234\" : things + +/^$/ + \ + +/ ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/x + ab c + abc + ab cde + +/(?x) ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/ + ab c + abc + ab cde + +/^ a\ b[c ]d $/x + a bcd + a b d + abcd + ab d + +/^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/ + abcdefhijklm + +/^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$/ + abcdefhijklm + +/^[\w][\W][\s][\S][\d][\D][\b][\n][\c]][\022]/ + a+ Z0+\x08\n\x1d\x12 + +/^[.^$|()*+?{,}]+/ + .^\$(*+)|{?,?} + +/^a*\w/ + z + az + aaaz + a + aa + aaaa + a+ + aa+ + +/^a*?\w/ + z + az + aaaz + a + aa + aaaa + a+ + aa+ + +/^a+\w/ + az + aaaz + aa + aaaa + aa+ + +/^a+?\w/ + az + aaaz + aa + aaaa + aa+ + +/^\d{8}\w{2,}/ + 1234567890 + 12345678ab + 12345678__ + 1234567 + +/^[aeiou\d]{4,5}$/ + uoie + 1234 + 12345 + aaaaa + 123456 + +/^[aeiou\d]{4,5}?/ + uoie + 1234 + 12345 + aaaaa + 123456 + +/\A(abc|def)=(\1){2,3}\Z/ + abc=abcabc + def=defdefdef + abc=defdef + +/^(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\11*(\3\4)\1(?#)2$/ + abcdefghijkcda2 + abcdefghijkkkkcda2 + +/(cat(a(ract|tonic)|erpillar)) \1()2(3)/ + cataract cataract23 + catatonic catatonic23 + caterpillar caterpillar23 + + +/^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/ + From abcd Mon Sep 01 12:33:02 1997 + +/^From\s+\S+\s+([a-zA-Z]{3}\s+){2}\d{1,2}\s+\d\d:\d\d/ + From abcd Mon Sep 01 12:33:02 1997 + From abcd Mon Sep 1 12:33:02 1997 + From abcd Sep 01 12:33:02 1997 + +/^12.34/s + 12\n34 + 12\r34 + +/\w+(?=\t)/ + the quick brown\t fox + +/foo(?!bar)(.*)/ + foobar is foolish see? + +/(?:(?!foo)...|^.{0,2})bar(.*)/ + foobar crowbar etc + barrel + 2barrel + A barrel + +/^(\D*)(?=\d)(?!123)/ + abc456 + abc123 + +/^1234(?# test newlines + inside)/ + 1234 + +/^1234 #comment in extended re + /x + 1234 + +/#rhubarb + abcd/x + abcd + +/^abcd#rhubarb/x + abcd + +/^(a)\1{2,3}(.)/ + aaab + aaaab + aaaaab + aaaaaab + +/(?!^)abc/ + the abc + abc + +/(?=^)abc/ + abc + the abc + +/^[ab]{1,3}(ab*|b)/ + aabbbbb + +/^[ab]{1,3}?(ab*|b)/ + aabbbbb + +/^[ab]{1,3}?(ab*?|b)/ + aabbbbb + +/^[ab]{1,3}(ab*?|b)/ + aabbbbb + +/ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* # optional leading comment +(?: (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) # initial word +(?: (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) )* # further okay, if led by a period +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* @ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # initial subdomain +(?: # +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. # if led by a period... +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # ...further okay +)* +# address +| # or +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) # one word, optionally followed by.... +(?: +[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] | # atom and space parts, or... +\( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) | # comments, or... + +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +# quoted strings +)* +< (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* # leading < +(?: @ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # initial subdomain +(?: # +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. # if led by a period... +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # ...further okay +)* + +(?: (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* , (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* @ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # initial subdomain +(?: # +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. # if led by a period... +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # ...further okay +)* +)* # further okay, if led by comma +: # closing colon +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* )? # optional route +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) # initial word +(?: (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +" (?: # opening quote... +[^\\\x80-\xff\n\015"] # Anything except backslash and quote +| # or +\\ [^\x80-\xff] # Escaped something (something != CR) +)* " # closing quote +) )* # further okay, if led by a period +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* @ (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # initial subdomain +(?: # +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* \. # if led by a period... +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* (?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| \[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) # ...further okay +)* +# address spec +(?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* > # trailing > +# name and address +) (?: [\040\t] | \( +(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* +\) )* # optional trailing comment +/x + Alan Other + + user\@dom.ain + \"A. Other\" (a comment) + A. Other (a comment) + \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay + A missing angle @,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address +| # or +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +# leading word +[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # "normal" atoms and or spaces +(?: +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +| +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +) # "special" comment or quoted string +[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # more "normal" +)* +< +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# < +(?: +@ +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +(?: , +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +@ +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +)* # additional domains +: +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)? # optional route +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +# Atom +| # or +" # " +[^\\\x80-\xff\n\015"] * # normal +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* +" # " +# Quoted string +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# additional words +)* +@ +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +(?: +\. +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +(?: +[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... +(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom +| +\[ # [ +(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff +\] # ] +) +[\040\t]* # Nab whitespace. +(?: +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: # ( +(?: \\ [^\x80-\xff] | +\( # ( +[^\\\x80-\xff\n\015()] * # normal* +(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* +\) # ) +) # special +[^\\\x80-\xff\n\015()] * # normal* +)* # )* +\) # ) +[\040\t]* )* # If comment found, allow more spaces. +# optional trailing comments +)* +# address spec +> # > +# name and address +) +/x + Alan Other + + user\@dom.ain + \"A. Other\" (a comment) + A. Other (a comment) + \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay + A missing angle ]{0,})>]{0,})>([\d]{0,}\.)(.*)((
([\w\W\s\d][^<>]{0,})|[\s]{0,}))<\/a><\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><\/TR>/is + 43.
Word Processor
(N-1286)
Lega lstaff.comCA - Statewide + +/a[^a]b/ + acb + a\nb + +/a.b/ + acb + a\nb + +/a[^a]b/s + acb + a\nb + +/a.b/s + acb + a\nb + +/^(b+?|a){1,2}?c/ + bac + bbac + bbbac + bbbbac + bbbbbac + +/^(b+|a){1,2}?c/ + bac + bbac + bbbac + bbbbac + bbbbbac + +/(?!\A)x/m + x\nb\n + a\bx\n + +/\x0{ab}/ + \0{ab} + +/(A|B)*?CD/ + CD + +/(A|B)*CD/ + CD + +/(AB)*?\1/ + ABABAB + +/(AB)*\1/ + ABABAB + +/(/ + doesn't matter + +/(x)\2/ + doesn't matter + +/((a{0,5}){0,5}){0,5}[c]/ + aaaaaaaaaac + aaaaaaaaaa + +/((a{0,5}){0,5})*[c]/ + aaaaaaaaaac + aaaaaaaaaa + +/(\b)*a/ + a + +/(a)*b/ + ab + +/(a|)*b/ + ab + b + x + +/^(?:(a)|(b))*\1\2$/ + abab + +/abc[^x]def/ + abcxabcydef + +/^(a|\1x)*$/ + aax + aaxa + +// + @{['']} + +/^(?:(a)|(b))*$/ + ab + +/[\0]/ + a + \0 + +/[\1]/ + a + \1 + +/\10()()()()()()()()()/ + doesn't matter + +/\10()()()()()()()()()()/ + a + +/a(?<)b/ + ab + +/[]/ + doesn't matter + +/[\]/ + doesn't matter + +/()/ + a + +/[\x]/ + x + \0 + +/((a)*)*/ + a + +/()a\1/ + a + +/a\1()/ + a + +/a(?i)a(?-i)a/ + aaa + aAa + aAA + +/a(?i)a(?-i)a(?i)a(?-i)a/ + aaaaa + aAaAa + AaAaA + aAAAa + AaaaA + AAAAA + aaAAA + AAaaa + +/\x/ + a + X + \0 + +/[a-c-e]/ + a + b + d + - + +/[b-\d]/ + b + c + d + - + 1 + +/[\d-f]/ + d + e + f + - + 1 + +/[/ + doesn't matter + +/]/ + ] + a + +/[]/ + doesn't matter + +/[-a-c]/ + - + a + b + d + +/[a-c-]/ + - + a + b + d + +/[-]/ + a + - + +/[--]/ + a + - + +/[---]/ + a + - + +/[--b]/ + - + a + c + +/[b--]/ + doesn't matter + +/a{/ + a{ + +/a{}/ + a{} + +/a{3/ + a{3 + +/a{3,/ + a{3, + +/a{3, 3}/ + a{3,3} + a{3, 3} + aaa + +/a{3, 3}/x + a{3,3} + a{3, 3} + aaa + +/a{3, }/ + a{3,} + a{3, } + aaa + +/a{3, }/x + a{3,} + a{3, } + aaa + +/\x x/ + \0 x + \0x + +/\x x/x + \0 x + \0x + +/\x 3/ + \0003 + \000 3 + x3 + x 3 + +/\x 3/x + \0003 + \000 3 + x3 + x 3 + +/^a{ 1}$/ + a + a{ 1} + a{1} + +/^a{ 1}$/x + a + a{ 1} + a{1} + +/{}/ + {} + a + +/{1}/ + doesn't matter + +/*/ + doesn't matter + +/|/ + x + +/\0000/ + \0000 + +/a(?<)b/ + ab + +/a(?i)b/ + ab + aB + Ab + +/a(?i=a)/ + doesn't matter + +/a(?<=a){3000}a/ + aa + xa + ax + +/a(?!=a){3000}a/ + aa + ax + xa + +/a(){3000}a/ + aa + ax + xa + +/a(?:){3000}a/ + aa + ax + +/a(?<=a)*a/ + aa + ax + xa + +/a(?!=a)*a/ + aa + ax + xa + +/a()*a/ + aa + ax + xa + +/a(?:)*a/ + aa + ax + xa + +/x(?<=a)*a/ + aa + xa + ax + +/a(?<=(a))*\1/ + aa + +/a(?<=(a))*?\1/ + aa + +/(?=(a)\1)*aa/ + aa + +/^((a|b){2,5}){2}$/ + aaaaabbbbb + +/^(b*|ba){1,2}bc/ + babc + bbabc + bababc + bababbc + babababc + +/^a{4,5}(?:c|a)c$/ + aaaaac + aaaaaac + +/^(a|){4,5}(?:c|a)c$/ + aaaaac + aaaaaac + +/(?m:^).abc$/ + eeexabc + eee\nxabc + +/(?m:^)abc/ + abc + \nabc + + +/^abc/ + abc + \nabc + +/\Aabc/ + abc + \nabc + +/(?.*/)foo" + /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/it/you/see/ + +"(?>.*/)foo" + /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo + +/(?>(\.\d\d[1-9]?))\d+/ + 1.230003938 + 1.875000282 + 1.235 + +/^((?>\w+)|(?>\s+))*$/ + now is the time for all good men to come to the aid of the party + this is not a line with only words and spaces! + +/(\d+)(\w)/ + 12345a + 12345+ + +/((?>\d+))(\w)/ + 12345a + 12345+ + +/(?>a+)b/ + aaab + +/((?>a+)b)/ + aaab + +/(?>(a+))b/ + aaab + +/(?>b)+/ + aaabbbccc + +/(?>a+|b+|c+)*c/ + aaabbbbccccd + +/((?>[^()]+)|\([^()]*\))+/ + ((abc(ade)ufh()()x + +/\(((?>[^()]+)|\([^()]+\))+\)/ + (abc) + (abc(def)xyz) + ((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +/a(?-i)b/i + ab + Ab + aB + AB + +/(a (?x)b c)d e/ + a bcd e + a b cd e + abcd e + a bcde + +/(a b(?x)c d (?-x)e f)/ + a bcde f + abcdef + +/(a(?i)b)c/ + abc + aBc + abC + aBC + Abc + ABc + ABC + AbC + +/a(?i:b)c/ + abc + aBc + ABC + abC + aBC + +/a(?i:b)*c/ + aBc + aBBc + aBC + aBBC + +/a(?=b(?i)c)\w\wd/ + abcd + abCd + aBCd + abcD + +/(?s-i:more.*than).*million/i + more than million + more than MILLION + more \n than Million + MORE THAN MILLION + more \n than \n million + +/(?:(?s-i)more.*than).*million/i + more than million + more than MILLION + more \n than Million + MORE THAN MILLION + more \n than \n million + +/(?>a(?i)b+)+c/ + abc + aBbc + aBBc + Abc + abAb + abbC + +/(?=a(?i)b)\w\wc/ + abc + aBc + Ab + abC + aBC + +/(?<=a(?i)b)(\w\w)c/ + abxxc + aBxxc + Abxxc + ABxxc + abxxC + +/(?:(a)|b)(?(1)A|B)/ + aA + bB + aB + bA + +/^(a)?(?(1)a|b)+$/ + aa + b + bb + ab + +/^(?(?=abc)\w{3}:|\d\d)$/ + abc: + 12 + 123 + xyz + +/^(?(?!abc)\d\d|\w{3}:)$/ + abc: + 12 + 123 + xyz + +/(?(?<=foo)bar|cat)/ + foobar + cat + fcat + focat + foocat + +/(?(?a*)*/ + a + aa + aaaa + +/(abc|)+/ + abc + abcabc + abcabcabc + xyz + +/([a]*)*/ + a + aaaaa + +/([ab]*)*/ + a + b + ababab + aaaabcde + bbbb + +/([^a]*)*/ + b + bbbb + aaa + +/([^ab]*)*/ + cccc + abab + +/([a]*?)*/ + a + aaaa + +/([ab]*?)*/ + a + b + abab + baba + +/([^a]*?)*/ + b + bbbb + aaa + +/([^ab]*?)*/ + c + cccc + baba + +/(?>a*)*/ + a + aaabcde + +/((?>a*))*/ + aaaaa + aabbaa + +/((?>a*?))*/ + aaaaa + aabbaa + +/(?(?=[^a-z]+[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) /x + 12-sep-98 + 12-09-98 + sep-12-98 + +/(?<=(foo))bar\1/ + foobarfoo + foobarfootling + foobar + barfoo + +/(?i:saturday|sunday)/ + saturday + sunday + Saturday + Sunday + SATURDAY + SUNDAY + SunDay + +/(a(?i)bc|BB)x/ + abcx + aBCx + bbx + BBx + abcX + aBCX + bbX + BBX + +/^([ab](?i)[cd]|[ef])/ + ac + aC + bD + elephant + Europe + frog + France + Africa + +/^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/ + ab + aBd + xy + xY + zebra + Zambesi + aCD + XY + +/(?<=foo\n)^bar/m + foo\nbar + bar + baz\nbar + +/(?<=(?]&/ + <&OUT + +/^(a\1?){4}$/ + aaaaaaaaaa + AB + aaaaaaaaa + aaaaaaaaaaa + +/^(a(?(1)\1)){4}$/ + aaaaaaaaaa + aaaaaaaaa + aaaaaaaaaaa + +/(?:(f)(o)(o)|(b)(a)(r))*/ + foobar + +/(?<=a)b/ + ab + cb + b + +/(?a+)ab/ + +/(?>a+)b/ + aaab + +/([[:]+)/ + a:[b]: + +/([[=]+)/ + a=[b]= + +/([[.]+)/ + a.[b]. + +/((?>a+)b)/ + aaab + +/(?>(a+))b/ + aaab + +/((?>[^()]+)|\([^()]*\))+/ + ((abc(ade)ufh()()x + +/a\Z/ + aaab + a\nb\n + +/b\Z/ + a\nb\n + +/b\z/ + +/b\Z/ + a\nb + +/b\z/ + a\nb + +/^(?>(?(1)\.|())[^\W_](?>[a-z0-9-]*[^\W_])?)+$/ + a + abc + a-b + 0-9 + a.b + 5.6.7 + the.quick.brown.fox + a100.b200.300c + 12-ab.1245 + \ + .a + -a + a- + a. + a_b + a.- + a.. + ab..bc + the.quick.brown.fox- + the.quick.brown.fox. + the.quick.brown.fox_ + the.quick.brown.fox+ + +/(?>.*)(?<=(abcd|wxyz))/ + alphabetabcd + endingwxyz + a rather long string that doesn't end with one of them + +/word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword/ + word cat dog elephant mussel cow horse canary baboon snake shark otherword + word cat dog elephant mussel cow horse canary baboon snake shark + +/word (?>[a-zA-Z0-9]+ ){0,30}otherword/ + word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope + +/(?<=\d{3}(?!999))foo/ + 999foo + 123999foo + 123abcfoo + +/(?<=(?!...999)\d{3})foo/ + 999foo + 123999foo + 123abcfoo + +/(?<=\d{3}(?!999)...)foo/ + 123abcfoo + 123456foo + 123999foo + +/(?<=\d{3}...)(?\s*)=(?>\s*) # find Z)+|A)*/ + ZABCDEFG + +/((?>)+|A)*/ + ZABCDEFG + +/a*/g + abbab + +/^[a-\d]/ + abcde + -things + 0digit + bcdef + +/^[\d-a]/ + abcde + -things + 0digit + bcdef + +/(?<=abc).*(?=def)/ + abcdef + abcxdef + abcxdefxdef + +/(?<=abc).*?(?=def)/ + abcdef + abcxdef + abcxdefxdef + +/(?<=abc).+(?=def)/ + abcdef + abcxdef + abcxdefxdef + +/(?<=abc).+?(?=def)/ + abcdef + abcxdef + abcxdefxdef + +/(?<=\b)(.*)/ + -abcdef + abcdef + +/(?<=\B)(.*)/ + -abcdef + abcdef + +/^'[ab]'/ + 'a' + 'b' + x'a' + 'a'x + 'ab' + +/^'[ab]'$/ + 'a' + 'b' + x'a' + 'a'x + 'ab' + +/'[ab]'$/ + 'a' + 'b' + x'a' + 'a'x + 'ab' + +/'[ab]'/ + 'a' + 'b' + x'a' + 'a'x + 'ab' + +/abc\E/ + abc + abcE + +/abc[\Ex]/ + abcx + abcE + +/^\Qa*\E$/ + a* + a + +/\Qa*x\E/ + a*x + a* + +/\Qa*x/ + a*x + a* + +/\Q\Qa*x\E\E/ + a*x + a\\*x + +/\Q\Qa*x\E/ + a*x + a\\*x + +/a\Q[x\E]/ + a[x] + ax + +/a#comment\Q... +{2}/x + a + aa + +/a(?#comment\Q... +){2}/x + a + aa + +/(?x)a#\Q +./ + a. + aa + +/ab(?=.*q)cd/ + abcdxklqj + +/a(?!.*$)b/ + ab + +/.{2}[a-z]/ + Axi \ No newline at end of file diff --git a/practicals/libraries/cl-ppcre-1.2.3/util.lisp b/practicals/libraries/cl-ppcre-1.2.3/util.lisp new file mode 100644 index 0000000..9638283 --- /dev/null +++ b/practicals/libraries/cl-ppcre-1.2.3/util.lisp @@ -0,0 +1,313 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/cl-ppcre/util.lisp,v 1.27 2005/01/24 14:06:38 edi Exp $ + +;;; Utility functions and constants dealing with the hash-tables +;;; we use to encode character classes + +;;; Hash-tables are treated like sets, i.e. a character C is a member of the +;;; hash-table H iff (GETHASH C H) is true. + +;;; Copyright (c) 2002-2004, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package #:cl-ppcre) + +(defmacro with-unique-names ((&rest bindings) &body body) + "Syntax: WITH-UNIQUE-NAMES ( { var | (var x) }* ) declaration* form* + +Executes a series of forms with each VAR bound to a fresh, +uninterned symbol. The uninterned symbol is as if returned by a call +to GENSYM with the string denoted by X - or, if X is not supplied, the +string denoted by VAR - as argument. + +The variable bindings created are lexical unless special declarations +are specified. The scopes of the name bindings and declarations do not +include the Xs. + +The forms are evaluated in order, and the values of all but the last +are discarded \(that is, the body is an implicit PROGN)." + ;; reference implementation posted to comp.lang.lisp as + ;; by Vebjorn Ljosa - see also + ;; + `(let ,(mapcar #'(lambda (binding) + (check-type binding (or cons symbol)) + (if (consp binding) + (destructuring-bind (var x) binding + (check-type var symbol) + `(,var (gensym ,(etypecase x + (symbol (symbol-name x)) + (character (string x)) + (string x))))) + `(,binding (gensym ,(symbol-name binding))))) + bindings) + ,@body)) + +(defmacro with-rebinding (bindings &body body) + "WITH-REBINDING ( { var | (var prefix) }* ) form* + +Evaluates a series of forms in the lexical environment that is +formed by adding the binding of each VAR to a fresh, uninterned +symbol, and the binding of that fresh, uninterned symbol to VAR's +original value, i.e., its value in the current lexical environment. + +The uninterned symbol is created as if by a call to GENSYM with the +string denoted by PREFIX - or, if PREFIX is not supplied, the string +denoted by VAR - as argument. + +The forms are evaluated in order, and the values of all but the last +are discarded \(that is, the body is an implicit PROGN)." + ;; reference implementation posted to comp.lang.lisp as + ;; by Vebjorn Ljosa - see also + ;; + (loop for binding in bindings + for var = (if (consp binding) (car binding) binding) + for name = (gensym) + collect `(,name ,var) into renames + collect ``(,,var ,,name) into temps + finally (return `(let ,renames + (with-unique-names ,bindings + `(let (,,@temps) + ,,@body)))))) + +(eval-when (:compile-toplevel :execute :load-toplevel) + (defvar *regex-char-code-limit* char-code-limit + "The upper exclusive bound on the char-codes of characters +which can occur in character classes. +Change this value BEFORE creating scanners if you don't need +the full Unicode support of LW, ACL, or CLISP.") + (declaim (type fixnum *regex-char-code-limit*)) + + (defun make-char-hash (test) + (declare (optimize speed space)) + "Returns a hash-table of all characters satisfying test." + (loop with hash = (make-hash-table) + for c of-type fixnum from 0 below char-code-limit + for chr = (code-char c) + if (and chr (funcall test chr)) + do (setf (gethash chr hash) t) + finally (return hash))) + + (declaim (inline word-char-p)) + + (defun word-char-p (chr) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Tests whether a character is a \"word\" character. +In the ASCII charset this is equivalent to a-z, A-Z, 0-9, or _, +i.e. the same as Perl's [\\w]." + (or (alphanumericp chr) + (char= chr #\_))) + + (unless (boundp '+whitespace-char-string+) + (defconstant +whitespace-char-string+ + (coerce + '(#\Space #\Tab #\Linefeed #\Return #\Page) + 'string) + "A string of all characters which are considered to be whitespace. +Same as Perl's [\\s].")) + + (defun whitespacep (chr) + (declare (optimize speed space)) + "Tests whether a character is whitespace, +i.e. whether it would match [\\s] in Perl." + (find chr +whitespace-char-string+ :test #'char=))) + +;; the following DEFCONSTANT statements are wrapped with +;; (UNLESS (BOUNDP ...) ...) to make SBCL happy + +(unless (boundp '+digit-hash+) + (defconstant +digit-hash+ + (make-char-hash (lambda (chr) (char<= #\0 chr #\9))) + "Hash-table containing the digits from 0 to 9.")) + +(unless (boundp '+word-char-hash+) + (defconstant +word-char-hash+ + (make-char-hash #'word-char-p) + "Hash-table containing all \"word\" characters.")) + +(unless (boundp '+whitespace-char-hash+) + (defconstant +whitespace-char-hash+ + (make-char-hash #'whitespacep) + "Hash-table containing all whitespace characters.")) + +(defun merge-hash (hash1 hash2) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Returns the \"sum\" of two hashes. This is a destructive operation +on HASH1." + (cond ((> (hash-table-count hash2) + *regex-char-code-limit*) + ;; don't walk through, e.g., the whole +WORD-CHAR-HASH+ if + ;; the user has set *REGEX-CHAR-CODE-LIMIT* to a lower value + (loop for c of-type fixnum from 0 below *regex-char-code-limit* + for chr = (code-char c) + if (and chr (gethash chr hash2)) + do (setf (gethash chr hash1) t))) + (t + (loop for chr being the hash-keys of hash2 + do (setf (gethash chr hash1) t)))) + hash1) + +(defun merge-inverted-hash (hash1 hash2) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Returns the \"sum\" of HASH1 and the \"inverse\" of HASH2. This is +a destructive operation on HASH1." + (loop for c of-type fixnum from 0 below *regex-char-code-limit* + for chr = (code-char c) + if (and chr (not (gethash chr hash2))) + do (setf (gethash chr hash1) t)) + hash1) + +(defun create-ranges-from-hash (hash &key downcasep) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Tries to identify up to three intervals (with respect to CHAR<) +which together comprise HASH. Returns NIL if this is not possible. +If DOWNCASEP is true it will treat the hash-table as if it represents +both the lower-case and the upper-case variants of its members and +will only return the respective lower-case intervals." + ;; discard empty hash-tables + (unless (and hash (plusp (hash-table-count hash))) + (return-from create-ranges-from-hash nil)) + (loop with min1 and min2 and min3 + and max1 and max2 and max3 + ;; loop through all characters in HASH, sorted by CHAR< + for chr in (sort (the list + (loop for chr being the hash-keys of hash + collect (if downcasep + (char-downcase chr) + chr))) + #'char<) + for code = (char-code chr) + ;; MIN1, MAX1, etc. are _exclusive_ + ;; bounds of the intervals identified so far + do (cond + ((not min1) + ;; this will only happen once, for the first character + (setq min1 (1- code) + max1 (1+ code))) + ((<= (the fixnum min1) code (the fixnum max1)) + ;; we're here as long as CHR fits into the first interval + (setq min1 (min (the fixnum min1) (1- code)) + max1 (max (the fixnum max1) (1+ code)))) + ((not min2) + ;; we need to open a second interval + ;; this'll also happen only once + (setq min2 (1- code) + max2 (1+ code))) + ((<= (the fixnum min2) code (the fixnum max2)) + ;; CHR fits into the second interval + (setq min2 (min (the fixnum min2) (1- code)) + max2 (max (the fixnum max2) (1+ code)))) + ((not min3) + ;; we need to open the third interval + ;; happens only once + (setq min3 (1- code) + max3 (1+ code))) + ((<= (the fixnum min3) code (the fixnum max3)) + ;; CHR fits into the third interval + (setq min3 (min (the fixnum min3) (1- code)) + max3 (max (the fixnum max3) (1+ code)))) + (t + ;; we're out of luck, CHR doesn't fit + ;; into one of the three intervals + (return nil))) + ;; on success return all bounds + ;; make them inclusive bounds before returning + finally (return (values (code-char (1+ min1)) + (code-char (1- max1)) + (and min2 (code-char (1+ min2))) + (and max2 (code-char (1- max2))) + (and min3 (code-char (1+ min3))) + (and max3 (code-char (1- max3))))))) + +(defmacro maybe-coerce-to-simple-string (string) + (with-unique-names (=string=) + `(let ((,=string= ,string)) + (cond ((simple-string-p ,=string=) + ,=string=) + (t + (coerce ,=string= 'simple-string)))))) + +(declaim (inline nsubseq)) +(defun nsubseq (sequence start &optional (end (length sequence))) + "Return a subsequence by pointing to location in original sequence." + (make-array (- end start) + :element-type (array-element-type sequence) + :displaced-to sequence + :displaced-index-offset start)) + +(defun normalize-var-list (var-list) + "Utility function for REGISTER-GROUPS-BIND and +DO-REGISTER-GROUPS. Creates the long form \(a list of \(FUNCTION VAR) +entries) out of the short form of VAR-LIST." + (loop for element in var-list + if (consp element) + nconc (loop for var in (rest element) + collect (list (first element) var)) + else + collect (list '(function identity) element))) + +(defun string-list-to-simple-string (string-list) + (declare (optimize speed + (safety 0) + (space 0) + (debug 0) + (compilation-speed 0) + #+:lispworks (hcl:fixnum-safety 0))) + "Concatenates a list of strings to one simple-string." + ;; this function provided by JP Massar; note that we can't use APPLY + ;; with CONCATENATE here because of CALL-ARGUMENTS-LIMIT + (let ((total-size 0)) + (declare (type fixnum total-size)) + (dolist (string string-list) + #-genera (declare (type string string)) + (incf total-size (length string))) + (let ((result-string (make-sequence 'simple-string total-size)) + (curr-pos 0)) + (declare (type fixnum curr-pos)) + (dolist (string string-list) + #-genera (declare (type string string)) + (replace result-string string :start1 curr-pos) + (incf curr-pos (length string))) + result-string))) diff --git a/practicals/practicals.asd b/practicals/practicals.asd new file mode 100644 index 0000000..2c8be55 --- /dev/null +++ b/practicals/practicals.asd @@ -0,0 +1,27 @@ +(defpackage :com.gigamonkeys.practicals-system (:use :asdf :cl)) +(in-package :com.gigamonkeys.practicals-system) + +(require :aserve) + +(defsystem practicals + :name "practicals" + :author "Peter Seibel " + :version "1.0" + :maintainer "Peter Seibel " + :licence "BSD" + :description "All code from Practical Common Lisp." + :depends-on + (:binary-data + :html + :id3v2 + :macro-utilities + :mp3-browser + :mp3-database + :pathnames + :shoutcast + :simple-database + :spam + :test-framework + :url-function)) + +