clucumber 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/README.md +4 -9
- data/lib/clucumber/clucumber-bootstrap.lisp +32 -0
- data/lib/clucumber/vendor/cl-interpol/alias.lisp +55 -0
- data/lib/clucumber/vendor/cl-interpol/cl-interpol.asd +56 -0
- data/lib/clucumber/vendor/cl-interpol/load.lisp +53 -0
- data/lib/clucumber/vendor/cl-interpol/packages.lisp +40 -0
- data/lib/clucumber/vendor/cl-interpol/read.lisp +716 -0
- data/lib/clucumber/vendor/cl-interpol/specials.lisp +113 -0
- data/lib/clucumber/vendor/cl-interpol/test/packages.lisp +34 -0
- data/lib/clucumber/vendor/cl-interpol/test/tests.lisp +128 -0
- data/lib/clucumber/vendor/cl-interpol/test.lisp +177 -0
- data/lib/clucumber/vendor/cl-interpol/test2.lisp +6254 -0
- data/lib/clucumber/vendor/cl-interpol/unicode.lisp +13912 -0
- data/lib/clucumber/vendor/cl-interpol/util.lisp +122 -0
- data/lib/clucumber/vendor/cl-ppcre/api.lisp +1262 -0
- data/lib/clucumber/vendor/cl-ppcre/charmap.lisp +152 -0
- data/lib/clucumber/vendor/cl-ppcre/charset.lisp +242 -0
- data/lib/clucumber/vendor/cl-ppcre/chartest.lisp +98 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-test.asd +34 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/packages.lisp +38 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/resolver.lisp +61 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode.asd +58 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre.asd +79 -0
- data/lib/clucumber/vendor/cl-ppcre/closures.lisp +471 -0
- data/lib/clucumber/vendor/cl-ppcre/convert.lisp +875 -0
- data/lib/clucumber/vendor/cl-ppcre/errors.lisp +84 -0
- data/lib/clucumber/vendor/cl-ppcre/lexer.lisp +737 -0
- data/lib/clucumber/vendor/cl-ppcre/lispworks-defsystem.lisp +57 -0
- data/lib/clucumber/vendor/cl-ppcre/load.lisp +67 -0
- data/lib/clucumber/vendor/cl-ppcre/optimize.lisp +578 -0
- data/lib/clucumber/vendor/cl-ppcre/packages.lisp +68 -0
- data/lib/clucumber/vendor/cl-ppcre/parser.lisp +319 -0
- data/lib/clucumber/vendor/cl-ppcre/ppcre-tests.lisp +269 -0
- data/lib/clucumber/vendor/cl-ppcre/regex-class-util.lisp +555 -0
- data/lib/clucumber/vendor/cl-ppcre/regex-class.lisp +259 -0
- data/lib/clucumber/vendor/cl-ppcre/repetition-closures.lisp +833 -0
- data/lib/clucumber/vendor/cl-ppcre/scanner.lisp +506 -0
- data/lib/clucumber/vendor/cl-ppcre/specials.lisp +172 -0
- data/lib/clucumber/vendor/cl-ppcre/test/packages.lisp +37 -0
- data/lib/clucumber/vendor/cl-ppcre/test/perl-tests.lisp +150 -0
- data/lib/clucumber/vendor/cl-ppcre/test/tests.lisp +159 -0
- data/lib/clucumber/vendor/cl-ppcre/test/unicode-tests.lisp +80 -0
- data/lib/clucumber/vendor/cl-ppcre/util.lisp +201 -0
- data/lib/clucumber/vendor/cl-unicode/alias.lisp +135 -0
- data/lib/clucumber/vendor/cl-unicode/api.lisp +412 -0
- data/lib/clucumber/vendor/cl-unicode/build/char-info.lisp +133 -0
- data/lib/clucumber/vendor/cl-unicode/build/dump.lisp +239 -0
- data/lib/clucumber/vendor/cl-unicode/build/read.lisp +280 -0
- data/lib/clucumber/vendor/cl-unicode/build/util.lisp +182 -0
- data/lib/clucumber/vendor/cl-unicode/cl-unicode.asd +90 -0
- data/lib/clucumber/vendor/cl-unicode/conditions.lisp +54 -0
- data/lib/clucumber/vendor/cl-unicode/derived.lisp +120 -0
- data/lib/clucumber/vendor/cl-unicode/hash-tables.lisp +20 -0
- data/lib/clucumber/vendor/cl-unicode/lists.lisp +10 -0
- data/lib/clucumber/vendor/cl-unicode/methods.lisp +15 -0
- data/lib/clucumber/vendor/cl-unicode/packages.lisp +76 -0
- data/lib/clucumber/vendor/cl-unicode/specials.lisp +135 -0
- data/lib/clucumber/vendor/cl-unicode/test/packages.lisp +34 -0
- data/lib/clucumber/vendor/cl-unicode/test/tests.lisp +150 -0
- data/lib/clucumber/vendor/cl-unicode/test-functions.lisp +94 -0
- data/lib/clucumber/vendor/cl-unicode/util.lisp +274 -0
- data/lib/clucumber/vendor/lift/compare/fiveam-tests.lisp +14 -0
- data/lib/clucumber/vendor/lift/compare/lift-tests.lisp +13 -0
- data/lib/clucumber/vendor/lift/compare/rt-tests.lisp +16 -0
- data/lib/clucumber/vendor/lift/compare/xlunit-tests.lisp +15 -0
- data/lib/clucumber/vendor/lift/dev/changes.lisp +61 -0
- data/lib/clucumber/vendor/lift/dev/config.lisp +354 -0
- data/lib/clucumber/vendor/lift/dev/copy-file.lisp +117 -0
- data/lib/clucumber/vendor/lift/dev/introspection.lisp +232 -0
- data/lib/clucumber/vendor/lift/dev/lift-interface.lisp +56 -0
- data/lib/clucumber/vendor/lift/dev/lift-notes.lisp +202 -0
- data/lib/clucumber/vendor/lift/dev/lift-randomized.lisp +45 -0
- data/lib/clucumber/vendor/lift/dev/lift.lisp +2383 -0
- data/lib/clucumber/vendor/lift/dev/macros.lisp +229 -0
- data/lib/clucumber/vendor/lift/dev/measuring.lisp +156 -0
- data/lib/clucumber/vendor/lift/dev/packages.lisp +161 -0
- data/lib/clucumber/vendor/lift/dev/port.lisp +151 -0
- data/lib/clucumber/vendor/lift/dev/prototypes.lisp +282 -0
- data/lib/clucumber/vendor/lift/dev/random-testing.lisp +124 -0
- data/lib/clucumber/vendor/lift/dev/report-locations.lisp +13 -0
- data/lib/clucumber/vendor/lift/dev/reports.lisp +916 -0
- data/lib/clucumber/vendor/lift/dev/utilities.lisp +242 -0
- data/lib/clucumber/vendor/lift/docs/package.lisp +6 -0
- data/lib/clucumber/vendor/lift/docs/setup.lisp +17 -0
- data/lib/clucumber/vendor/lift/examples/basic-examples.lisp +289 -0
- data/lib/clucumber/vendor/lift/examples/random-testing.lisp +32 -0
- data/lib/clucumber/vendor/lift/lift-documentation.asd +28 -0
- data/lib/clucumber/vendor/lift/lift-test.asd +35 -0
- data/lib/clucumber/vendor/lift/lift.asd +77 -0
- data/lib/clucumber/vendor/lift/test/equality-tests.lisp +40 -0
- data/lib/clucumber/vendor/lift/test/finding-tests.lisp +32 -0
- data/lib/clucumber/vendor/lift/test/lift-test.lisp +783 -0
- data/lib/clucumber/vendor/lift/test/order-of-operations.lisp +54 -0
- data/lib/clucumber/vendor/lift/test/packages.lisp +17 -0
- data/lib/clucumber/vendor/lift/test/test-config-files.lisp +20 -0
- data/lib/clucumber/vendor/lift/test/test-dynamic-variables.lisp +57 -0
- data/lib/clucumber/vendor/lift/test/test-maximum-problems.lisp +74 -0
- data/lib/clucumber/vendor/lift/test/test-prototypes.lisp +278 -0
- data/lib/clucumber/vendor/lift/test/test-timeout.lisp +37 -0
- data/lib/clucumber/vendor/lift/test/tests-in-progress.lisp +62 -0
- data/lib/clucumber/vendor/lift/test/testsuite-expects.lisp +60 -0
- data/lib/clucumber/vendor/lift/timeout/package.lisp +13 -0
- data/lib/clucumber/vendor/lift/timeout/with-timeout.lisp +123 -0
- data/lib/clucumber/vendor/lift/website/stuff/Temp.lisp +34 -0
- data/lib/clucumber/vendor/st-json/st-json.asd +3 -0
- data/lib/clucumber/vendor/st-json/st-json.lisp +310 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/backtrace.lisp +127 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/fallback.lisp +10 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/map-backtrace.lisp +103 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/mucking.lisp +75 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/packages.lisp +13 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/utilities.lisp +104 -0
- data/lib/clucumber/vendor/trivial-backtrace/test/packages.lisp +5 -0
- data/lib/clucumber/vendor/trivial-backtrace/test/test-setup.lisp +4 -0
- data/lib/clucumber/vendor/trivial-backtrace/test/tests.lisp +16 -0
- data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace-test.asd +22 -0
- data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace.asd +35 -0
- data/lib/clucumber/vendor/usocket/backend/allegro.lisp +199 -0
- data/lib/clucumber/vendor/usocket/backend/armedbear.lisp +491 -0
- data/lib/clucumber/vendor/usocket/backend/clisp.lisp +260 -0
- data/lib/clucumber/vendor/usocket/backend/cmucl.lisp +266 -0
- data/lib/clucumber/vendor/usocket/backend/lispworks.lisp +741 -0
- data/lib/clucumber/vendor/usocket/backend/mcl.lisp +369 -0
- data/lib/clucumber/vendor/usocket/backend/openmcl.lisp +206 -0
- data/lib/clucumber/vendor/usocket/backend/sbcl.lisp +424 -0
- data/lib/clucumber/vendor/usocket/backend/scl.lisp +261 -0
- data/lib/clucumber/vendor/usocket/condition.lisp +227 -0
- data/lib/clucumber/vendor/usocket/package.lisp +82 -0
- data/lib/clucumber/vendor/usocket/server.lisp +45 -0
- data/lib/clucumber/vendor/usocket/test/package.lisp +13 -0
- data/lib/clucumber/vendor/usocket/test/test-usocket.lisp +166 -0
- data/lib/clucumber/vendor/usocket/usocket-test.asd +26 -0
- data/lib/clucumber/vendor/usocket/usocket.asd +37 -0
- data/lib/clucumber/vendor/usocket/usocket.lisp +542 -0
- data/lib/clucumber/vendor/usocket/vendor/kqueue.lisp +1 -0
- data/lib/clucumber/vendor/usocket/vendor/split-sequence.lisp +245 -0
- data/lib/clucumber.rb +29 -7
- metadata +151 -5
@@ -0,0 +1,506 @@
|
|
1
|
+
;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*-
|
2
|
+
;;; $Header: /usr/local/cvsrep/cl-ppcre/scanner.lisp,v 1.36 2009/09/17 19:17:31 edi Exp $
|
3
|
+
|
4
|
+
;;; Here the scanner for the actual regex as well as utility scanners
|
5
|
+
;;; for the constant start and end strings are created.
|
6
|
+
|
7
|
+
;;; Copyright (c) 2002-2009, Dr. Edmund Weitz. All rights reserved.
|
8
|
+
|
9
|
+
;;; Redistribution and use in source and binary forms, with or without
|
10
|
+
;;; modification, are permitted provided that the following conditions
|
11
|
+
;;; are met:
|
12
|
+
|
13
|
+
;;; * Redistributions of source code must retain the above copyright
|
14
|
+
;;; notice, this list of conditions and the following disclaimer.
|
15
|
+
|
16
|
+
;;; * Redistributions in binary form must reproduce the above
|
17
|
+
;;; copyright notice, this list of conditions and the following
|
18
|
+
;;; disclaimer in the documentation and/or other materials
|
19
|
+
;;; provided with the distribution.
|
20
|
+
|
21
|
+
;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
|
22
|
+
;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
23
|
+
;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
24
|
+
;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
25
|
+
;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
26
|
+
;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
27
|
+
;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
28
|
+
;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
29
|
+
;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
30
|
+
;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
31
|
+
;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
32
|
+
|
33
|
+
(in-package :cl-ppcre)
|
34
|
+
|
35
|
+
(defmacro bmh-matcher-aux (&key case-insensitive-p)
|
36
|
+
"Auxiliary macro used by CREATE-BMH-MATCHER."
|
37
|
+
(let ((char-compare (if case-insensitive-p 'char-equal 'char=)))
|
38
|
+
`(lambda (start-pos)
|
39
|
+
(declare (fixnum start-pos))
|
40
|
+
(if (or (minusp start-pos)
|
41
|
+
(> (the fixnum (+ start-pos m)) *end-pos*))
|
42
|
+
nil
|
43
|
+
(loop named bmh-matcher
|
44
|
+
for k of-type fixnum = (+ start-pos m -1)
|
45
|
+
then (+ k (max 1 (aref skip (char-code (schar *string* k)))))
|
46
|
+
while (< k *end-pos*)
|
47
|
+
do (loop for j of-type fixnum downfrom (1- m)
|
48
|
+
for i of-type fixnum downfrom k
|
49
|
+
while (and (>= j 0)
|
50
|
+
(,char-compare (schar *string* i)
|
51
|
+
(schar pattern j)))
|
52
|
+
finally (if (minusp j)
|
53
|
+
(return-from bmh-matcher (1+ i)))))))))
|
54
|
+
|
55
|
+
(defun create-bmh-matcher (pattern case-insensitive-p)
|
56
|
+
"Returns a Boyer-Moore-Horspool matcher which searches the (special)
|
57
|
+
simple-string *STRING* for the first occurence of the substring
|
58
|
+
PATTERN. The search starts at the position START-POS within *STRING*
|
59
|
+
and stops before *END-POS* is reached. Depending on the second
|
60
|
+
argument the search is case-insensitive or not. If the special
|
61
|
+
variable *USE-BMH-MATCHERS* is NIL, use the standard SEARCH function
|
62
|
+
instead. \(BMH matchers are faster but need much more space.)"
|
63
|
+
(declare #.*standard-optimize-settings*)
|
64
|
+
;; see <http://www-igm.univ-mlv.fr/~lecroq/string/node18.html> for
|
65
|
+
;; details
|
66
|
+
(unless *use-bmh-matchers*
|
67
|
+
(let ((test (if case-insensitive-p #'char-equal #'char=)))
|
68
|
+
(return-from create-bmh-matcher
|
69
|
+
(lambda (start-pos)
|
70
|
+
(declare (fixnum start-pos))
|
71
|
+
(and (not (minusp start-pos))
|
72
|
+
(search pattern
|
73
|
+
*string*
|
74
|
+
:start2 start-pos
|
75
|
+
:end2 *end-pos*
|
76
|
+
:test test))))))
|
77
|
+
(let* ((m (length pattern))
|
78
|
+
(skip (make-array *regex-char-code-limit*
|
79
|
+
:element-type 'fixnum
|
80
|
+
:initial-element m)))
|
81
|
+
(declare (fixnum m))
|
82
|
+
(loop for k of-type fixnum below m
|
83
|
+
if case-insensitive-p
|
84
|
+
do (setf (aref skip (char-code (char-upcase (schar pattern k)))) (- m k 1)
|
85
|
+
(aref skip (char-code (char-downcase (schar pattern k)))) (- m k 1))
|
86
|
+
else
|
87
|
+
do (setf (aref skip (char-code (schar pattern k))) (- m k 1)))
|
88
|
+
(if case-insensitive-p
|
89
|
+
(bmh-matcher-aux :case-insensitive-p t)
|
90
|
+
(bmh-matcher-aux))))
|
91
|
+
|
92
|
+
(defmacro char-searcher-aux (&key case-insensitive-p)
|
93
|
+
"Auxiliary macro used by CREATE-CHAR-SEARCHER."
|
94
|
+
(let ((char-compare (if case-insensitive-p 'char-equal 'char=)))
|
95
|
+
`(lambda (start-pos)
|
96
|
+
(declare (fixnum start-pos))
|
97
|
+
(and (not (minusp start-pos))
|
98
|
+
(loop for i of-type fixnum from start-pos below *end-pos*
|
99
|
+
thereis (and (,char-compare (schar *string* i) chr) i))))))
|
100
|
+
|
101
|
+
(defun create-char-searcher (chr case-insensitive-p)
|
102
|
+
"Returns a function which searches the (special) simple-string
|
103
|
+
*STRING* for the first occurence of the character CHR. The search
|
104
|
+
starts at the position START-POS within *STRING* and stops before
|
105
|
+
*END-POS* is reached. Depending on the second argument the search is
|
106
|
+
case-insensitive or not."
|
107
|
+
(declare #.*standard-optimize-settings*)
|
108
|
+
(if case-insensitive-p
|
109
|
+
(char-searcher-aux :case-insensitive-p t)
|
110
|
+
(char-searcher-aux)))
|
111
|
+
|
112
|
+
(declaim (inline newline-skipper))
|
113
|
+
(defun newline-skipper (start-pos)
|
114
|
+
"Finds the next occurence of a character in *STRING* which is behind
|
115
|
+
a #\Newline."
|
116
|
+
(declare #.*standard-optimize-settings*)
|
117
|
+
(declare (fixnum start-pos))
|
118
|
+
;; we can start with (1- START-POS) without testing for (PLUSP
|
119
|
+
;; START-POS) because we know we'll never call NEWLINE-SKIPPER on
|
120
|
+
;; the first iteration
|
121
|
+
(loop for i of-type fixnum from (1- start-pos) below *end-pos*
|
122
|
+
thereis (and (char= (schar *string* i)
|
123
|
+
#\Newline)
|
124
|
+
(1+ i))))
|
125
|
+
|
126
|
+
(defmacro insert-advance-fn (advance-fn)
|
127
|
+
"Creates the actual closure returned by CREATE-SCANNER-AUX by
|
128
|
+
replacing '(ADVANCE-FN-DEFINITION) with a suitable definition for
|
129
|
+
ADVANCE-FN. This is a utility macro used by CREATE-SCANNER-AUX."
|
130
|
+
(subst
|
131
|
+
advance-fn '(advance-fn-definition)
|
132
|
+
'(lambda (string start end)
|
133
|
+
(block scan
|
134
|
+
;; initialize a couple of special variables used by the
|
135
|
+
;; matchers (see file specials.lisp)
|
136
|
+
(let* ((*string* string)
|
137
|
+
(*start-pos* start)
|
138
|
+
(*end-pos* end)
|
139
|
+
;; we will search forward for END-STRING if this value
|
140
|
+
;; isn't at least as big as POS (see ADVANCE-FN), so it
|
141
|
+
;; is safe to start to the left of *START-POS*; note
|
142
|
+
;; that this value will _never_ be decremented - this
|
143
|
+
;; is crucial to the scanning process
|
144
|
+
(*end-string-pos* (1- *start-pos*))
|
145
|
+
;; the next five will shadow the variables defined by
|
146
|
+
;; DEFPARAMETER; at this point, we don't know if we'll
|
147
|
+
;; actually use them, though
|
148
|
+
(*repeat-counters* *repeat-counters*)
|
149
|
+
(*last-pos-stores* *last-pos-stores*)
|
150
|
+
(*reg-starts* *reg-starts*)
|
151
|
+
(*regs-maybe-start* *regs-maybe-start*)
|
152
|
+
(*reg-ends* *reg-ends*)
|
153
|
+
;; we might be able to optimize the scanning process by
|
154
|
+
;; (virtually) shifting *START-POS* to the right
|
155
|
+
(scan-start-pos *start-pos*)
|
156
|
+
(starts-with-str (if start-string-test
|
157
|
+
(str starts-with)
|
158
|
+
nil))
|
159
|
+
;; we don't need to try further than MAX-END-POS
|
160
|
+
(max-end-pos (- *end-pos* min-len)))
|
161
|
+
(declare (fixnum scan-start-pos)
|
162
|
+
(function match-fn))
|
163
|
+
;; definition of ADVANCE-FN will be inserted here by macrology
|
164
|
+
(labels ((advance-fn-definition))
|
165
|
+
(declare (inline advance-fn))
|
166
|
+
(when (plusp rep-num)
|
167
|
+
;; we have at least one REPETITION which needs to count
|
168
|
+
;; the number of repetitions
|
169
|
+
(setq *repeat-counters* (make-array rep-num
|
170
|
+
:initial-element 0
|
171
|
+
:element-type 'fixnum)))
|
172
|
+
(when (plusp zero-length-num)
|
173
|
+
;; we have at least one REPETITION which needs to watch
|
174
|
+
;; out for zero-length repetitions
|
175
|
+
(setq *last-pos-stores* (make-array zero-length-num
|
176
|
+
:initial-element nil)))
|
177
|
+
(when (plusp reg-num)
|
178
|
+
;; we have registers in our regular expression
|
179
|
+
(setq *reg-starts* (make-array reg-num :initial-element nil)
|
180
|
+
*regs-maybe-start* (make-array reg-num :initial-element nil)
|
181
|
+
*reg-ends* (make-array reg-num :initial-element nil)))
|
182
|
+
(when end-anchored-p
|
183
|
+
;; the regular expression has a constant end string which
|
184
|
+
;; is anchored at the very end of the target string
|
185
|
+
;; (perhaps modulo a #\Newline)
|
186
|
+
(let ((end-test-pos (- *end-pos* (the fixnum end-string-len))))
|
187
|
+
(declare (fixnum end-test-pos)
|
188
|
+
(function end-string-test))
|
189
|
+
(unless (setq *end-string-pos* (funcall end-string-test
|
190
|
+
end-test-pos))
|
191
|
+
(when (and (= 1 (the fixnum end-anchored-p))
|
192
|
+
(> *end-pos* scan-start-pos)
|
193
|
+
(char= #\Newline (schar *string* (1- *end-pos*))))
|
194
|
+
;; if we didn't find an end string candidate from
|
195
|
+
;; END-TEST-POS and if a #\Newline at the end is
|
196
|
+
;; allowed we try it again from one position to the
|
197
|
+
;; left
|
198
|
+
(setq *end-string-pos* (funcall end-string-test
|
199
|
+
(1- end-test-pos))))))
|
200
|
+
(unless (and *end-string-pos*
|
201
|
+
(<= *start-pos* *end-string-pos*))
|
202
|
+
;; no end string candidate found, so give up
|
203
|
+
(return-from scan nil))
|
204
|
+
(when end-string-offset
|
205
|
+
;; if the offset of the constant end string from the
|
206
|
+
;; left of the regular expression is known we can start
|
207
|
+
;; scanning further to the right; this is similar to
|
208
|
+
;; what we might do in ADVANCE-FN
|
209
|
+
(setq scan-start-pos (max scan-start-pos
|
210
|
+
(- (the fixnum *end-string-pos*)
|
211
|
+
(the fixnum end-string-offset))))))
|
212
|
+
(cond
|
213
|
+
(start-anchored-p
|
214
|
+
;; we're anchored at the start of the target string,
|
215
|
+
;; so no need to try again after first failure
|
216
|
+
(when (or (/= *start-pos* scan-start-pos)
|
217
|
+
(< max-end-pos *start-pos*))
|
218
|
+
;; if END-STRING-OFFSET has proven that we don't
|
219
|
+
;; need to bother to scan from *START-POS* or if the
|
220
|
+
;; minimal length of the regular expression is
|
221
|
+
;; longer than the target string we give up
|
222
|
+
(return-from scan nil))
|
223
|
+
(when starts-with-str
|
224
|
+
(locally
|
225
|
+
(declare (fixnum starts-with-len))
|
226
|
+
(cond ((and (case-insensitive-p starts-with)
|
227
|
+
(not (*string*-equal starts-with-str
|
228
|
+
*start-pos*
|
229
|
+
(+ *start-pos*
|
230
|
+
starts-with-len)
|
231
|
+
0 starts-with-len)))
|
232
|
+
;; the regular expression has a
|
233
|
+
;; case-insensitive constant start string
|
234
|
+
;; and we didn't find it
|
235
|
+
(return-from scan nil))
|
236
|
+
((and (not (case-insensitive-p starts-with))
|
237
|
+
(not (*string*= starts-with-str
|
238
|
+
*start-pos*
|
239
|
+
(+ *start-pos* starts-with-len)
|
240
|
+
0 starts-with-len)))
|
241
|
+
;; the regular expression has a
|
242
|
+
;; case-sensitive constant start string
|
243
|
+
;; and we didn't find it
|
244
|
+
(return-from scan nil))
|
245
|
+
(t nil))))
|
246
|
+
(when (and end-string-test
|
247
|
+
(not end-anchored-p))
|
248
|
+
;; the regular expression has a constant end string
|
249
|
+
;; which isn't anchored so we didn't check for it
|
250
|
+
;; already
|
251
|
+
(block end-string-loop
|
252
|
+
;; we temporarily use *END-STRING-POS* as our
|
253
|
+
;; starting position to look for end string
|
254
|
+
;; candidates
|
255
|
+
(setq *end-string-pos* *start-pos*)
|
256
|
+
(loop
|
257
|
+
(unless (setq *end-string-pos*
|
258
|
+
(funcall (the function end-string-test)
|
259
|
+
*end-string-pos*))
|
260
|
+
;; no end string candidate found, so give up
|
261
|
+
(return-from scan nil))
|
262
|
+
(unless end-string-offset
|
263
|
+
;; end string doesn't have an offset so we
|
264
|
+
;; can start scanning now
|
265
|
+
(return-from end-string-loop))
|
266
|
+
(let ((maybe-start-pos (- (the fixnum *end-string-pos*)
|
267
|
+
(the fixnum end-string-offset))))
|
268
|
+
(cond ((= maybe-start-pos *start-pos*)
|
269
|
+
;; offset of end string into regular
|
270
|
+
;; expression matches start anchor -
|
271
|
+
;; fine...
|
272
|
+
(return-from end-string-loop))
|
273
|
+
((and (< maybe-start-pos *start-pos*)
|
274
|
+
(< (+ *end-string-pos* end-string-len) *end-pos*))
|
275
|
+
;; no match but maybe we find another
|
276
|
+
;; one to the right - try again
|
277
|
+
(incf *end-string-pos*))
|
278
|
+
(t
|
279
|
+
;; otherwise give up
|
280
|
+
(return-from scan nil)))))))
|
281
|
+
;; if we got here we scan exactly once
|
282
|
+
(let ((next-pos (funcall match-fn *start-pos*)))
|
283
|
+
(when next-pos
|
284
|
+
(values (if next-pos *start-pos* nil)
|
285
|
+
next-pos
|
286
|
+
*reg-starts*
|
287
|
+
*reg-ends*))))
|
288
|
+
(t
|
289
|
+
(loop for pos = (if starts-with-everything
|
290
|
+
;; don't jump to the next
|
291
|
+
;; #\Newline on the first
|
292
|
+
;; iteration
|
293
|
+
scan-start-pos
|
294
|
+
(advance-fn scan-start-pos))
|
295
|
+
then (advance-fn pos)
|
296
|
+
;; give up if the regular expression can't fit
|
297
|
+
;; into the rest of the target string
|
298
|
+
while (and pos
|
299
|
+
(<= (the fixnum pos) max-end-pos))
|
300
|
+
do (let ((next-pos (funcall match-fn pos)))
|
301
|
+
(when next-pos
|
302
|
+
(return-from scan (values pos
|
303
|
+
next-pos
|
304
|
+
*reg-starts*
|
305
|
+
*reg-ends*)))
|
306
|
+
;; not yet found, increment POS
|
307
|
+
#-cormanlisp (incf (the fixnum pos))
|
308
|
+
#+cormanlisp (incf pos)))))))))
|
309
|
+
:test #'equalp))
|
310
|
+
|
311
|
+
(defun create-scanner-aux (match-fn
|
312
|
+
min-len
|
313
|
+
start-anchored-p
|
314
|
+
starts-with
|
315
|
+
start-string-test
|
316
|
+
end-anchored-p
|
317
|
+
end-string-test
|
318
|
+
end-string-len
|
319
|
+
end-string-offset
|
320
|
+
rep-num
|
321
|
+
zero-length-num
|
322
|
+
reg-num)
|
323
|
+
"Auxiliary function to create and return a scanner \(which is
|
324
|
+
actually a closure). Used by CREATE-SCANNER."
|
325
|
+
(declare #.*standard-optimize-settings*)
|
326
|
+
(declare (fixnum min-len zero-length-num rep-num reg-num))
|
327
|
+
(let ((starts-with-len (if (typep starts-with 'str)
|
328
|
+
(len starts-with)))
|
329
|
+
(starts-with-everything (typep starts-with 'everything)))
|
330
|
+
(cond
|
331
|
+
;; this COND statement dispatches on the different versions we
|
332
|
+
;; have for ADVANCE-FN and creates different closures for each;
|
333
|
+
;; note that you see only the bodies of ADVANCE-FN below - the
|
334
|
+
;; actual scanner is defined in INSERT-ADVANCE-FN above; (we
|
335
|
+
;; could have done this with closures instead of macrology but
|
336
|
+
;; would have consed a lot more)
|
337
|
+
((and start-string-test end-string-test end-string-offset)
|
338
|
+
;; we know that the regular expression has constant start and
|
339
|
+
;; end strings and we know the end string's offset (from the
|
340
|
+
;; left)
|
341
|
+
(insert-advance-fn
|
342
|
+
(advance-fn (pos)
|
343
|
+
(declare (fixnum end-string-offset starts-with-len)
|
344
|
+
(function start-string-test end-string-test))
|
345
|
+
(loop
|
346
|
+
(unless (setq pos (funcall start-string-test pos))
|
347
|
+
;; give up completely if we can't find a start string
|
348
|
+
;; candidate
|
349
|
+
(return-from scan nil))
|
350
|
+
(locally
|
351
|
+
;; from here we know that POS is a FIXNUM
|
352
|
+
(declare (fixnum pos))
|
353
|
+
(when (= pos (- (the fixnum *end-string-pos*) end-string-offset))
|
354
|
+
;; if we already found an end string candidate the
|
355
|
+
;; position of which matches the start string
|
356
|
+
;; candidate we're done
|
357
|
+
(return-from advance-fn pos))
|
358
|
+
(let ((try-pos (+ pos starts-with-len)))
|
359
|
+
;; otherwise try (again) to find an end string
|
360
|
+
;; candidate which starts behind the start string
|
361
|
+
;; candidate
|
362
|
+
(loop
|
363
|
+
(unless (setq *end-string-pos*
|
364
|
+
(funcall end-string-test try-pos))
|
365
|
+
;; no end string candidate found, so give up
|
366
|
+
(return-from scan nil))
|
367
|
+
;; NEW-POS is where we should start scanning
|
368
|
+
;; according to the end string candidate
|
369
|
+
(let ((new-pos (- (the fixnum *end-string-pos*)
|
370
|
+
end-string-offset)))
|
371
|
+
(declare (fixnum new-pos *end-string-pos*))
|
372
|
+
(cond ((= new-pos pos)
|
373
|
+
;; if POS and NEW-POS are equal then the
|
374
|
+
;; two candidates agree so we're fine
|
375
|
+
(return-from advance-fn pos))
|
376
|
+
((> new-pos pos)
|
377
|
+
;; if NEW-POS is further to the right we
|
378
|
+
;; advance POS and try again, i.e. we go
|
379
|
+
;; back to the start of the outer LOOP
|
380
|
+
(setq pos new-pos)
|
381
|
+
;; this means "return from inner LOOP"
|
382
|
+
(return))
|
383
|
+
(t
|
384
|
+
;; otherwise NEW-POS is smaller than POS,
|
385
|
+
;; so we have to redo the inner LOOP to
|
386
|
+
;; find another end string candidate
|
387
|
+
;; further to the right
|
388
|
+
(setq try-pos (1+ *end-string-pos*))))))))))))
|
389
|
+
((and starts-with-everything end-string-test end-string-offset)
|
390
|
+
;; we know that the regular expression starts with ".*" (which
|
391
|
+
;; is not in single-line-mode, see CREATE-SCANNER-AUX) and ends
|
392
|
+
;; with a constant end string and we know the end string's
|
393
|
+
;; offset (from the left)
|
394
|
+
(insert-advance-fn
|
395
|
+
(advance-fn (pos)
|
396
|
+
(declare (fixnum end-string-offset)
|
397
|
+
(function end-string-test))
|
398
|
+
(loop
|
399
|
+
(unless (setq pos (newline-skipper pos))
|
400
|
+
;; if we can't find a #\Newline we give up immediately
|
401
|
+
(return-from scan nil))
|
402
|
+
(locally
|
403
|
+
;; from here we know that POS is a FIXNUM
|
404
|
+
(declare (fixnum pos))
|
405
|
+
(when (= pos (- (the fixnum *end-string-pos*) end-string-offset))
|
406
|
+
;; if we already found an end string candidate the
|
407
|
+
;; position of which matches the place behind the
|
408
|
+
;; #\Newline we're done
|
409
|
+
(return-from advance-fn pos))
|
410
|
+
(let ((try-pos pos))
|
411
|
+
;; otherwise try (again) to find an end string
|
412
|
+
;; candidate which starts behind the #\Newline
|
413
|
+
(loop
|
414
|
+
(unless (setq *end-string-pos*
|
415
|
+
(funcall end-string-test try-pos))
|
416
|
+
;; no end string candidate found, so we give up
|
417
|
+
(return-from scan nil))
|
418
|
+
;; NEW-POS is where we should start scanning
|
419
|
+
;; according to the end string candidate
|
420
|
+
(let ((new-pos (- (the fixnum *end-string-pos*)
|
421
|
+
end-string-offset)))
|
422
|
+
(declare (fixnum new-pos *end-string-pos*))
|
423
|
+
(cond ((= new-pos pos)
|
424
|
+
;; if POS and NEW-POS are equal then the
|
425
|
+
;; the end string candidate agrees with
|
426
|
+
;; the #\Newline so we're fine
|
427
|
+
(return-from advance-fn pos))
|
428
|
+
((> new-pos pos)
|
429
|
+
;; if NEW-POS is further to the right we
|
430
|
+
;; advance POS and try again, i.e. we go
|
431
|
+
;; back to the start of the outer LOOP
|
432
|
+
(setq pos new-pos)
|
433
|
+
;; this means "return from inner LOOP"
|
434
|
+
(return))
|
435
|
+
(t
|
436
|
+
;; otherwise NEW-POS is smaller than POS,
|
437
|
+
;; so we have to redo the inner LOOP to
|
438
|
+
;; find another end string candidate
|
439
|
+
;; further to the right
|
440
|
+
(setq try-pos (1+ *end-string-pos*))))))))))))
|
441
|
+
((and start-string-test end-string-test)
|
442
|
+
;; we know that the regular expression has constant start and
|
443
|
+
;; end strings; similar to the first case but we only need to
|
444
|
+
;; check for the end string, it doesn't provide enough
|
445
|
+
;; information to advance POS
|
446
|
+
(insert-advance-fn
|
447
|
+
(advance-fn (pos)
|
448
|
+
(declare (function start-string-test end-string-test))
|
449
|
+
(unless (setq pos (funcall start-string-test pos))
|
450
|
+
(return-from scan nil))
|
451
|
+
(if (<= (the fixnum pos)
|
452
|
+
(the fixnum *end-string-pos*))
|
453
|
+
(return-from advance-fn pos))
|
454
|
+
(unless (setq *end-string-pos* (funcall end-string-test pos))
|
455
|
+
(return-from scan nil))
|
456
|
+
pos)))
|
457
|
+
((and starts-with-everything end-string-test)
|
458
|
+
;; we know that the regular expression starts with ".*" (which
|
459
|
+
;; is not in single-line-mode, see CREATE-SCANNER-AUX) and ends
|
460
|
+
;; with a constant end string; similar to the second case but we
|
461
|
+
;; only need to check for the end string, it doesn't provide
|
462
|
+
;; enough information to advance POS
|
463
|
+
(insert-advance-fn
|
464
|
+
(advance-fn (pos)
|
465
|
+
(declare (function end-string-test))
|
466
|
+
(unless (setq pos (newline-skipper pos))
|
467
|
+
(return-from scan nil))
|
468
|
+
(if (<= (the fixnum pos)
|
469
|
+
(the fixnum *end-string-pos*))
|
470
|
+
(return-from advance-fn pos))
|
471
|
+
(unless (setq *end-string-pos* (funcall end-string-test pos))
|
472
|
+
(return-from scan nil))
|
473
|
+
pos)))
|
474
|
+
(start-string-test
|
475
|
+
;; just check for constant start string candidate
|
476
|
+
(insert-advance-fn
|
477
|
+
(advance-fn (pos)
|
478
|
+
(declare (function start-string-test))
|
479
|
+
(unless (setq pos (funcall start-string-test pos))
|
480
|
+
(return-from scan nil))
|
481
|
+
pos)))
|
482
|
+
(starts-with-everything
|
483
|
+
;; just advance POS with NEWLINE-SKIPPER
|
484
|
+
(insert-advance-fn
|
485
|
+
(advance-fn (pos)
|
486
|
+
(unless (setq pos (newline-skipper pos))
|
487
|
+
(return-from scan nil))
|
488
|
+
pos)))
|
489
|
+
(end-string-test
|
490
|
+
;; just check for the next end string candidate if POS has
|
491
|
+
;; advanced beyond the last one
|
492
|
+
(insert-advance-fn
|
493
|
+
(advance-fn (pos)
|
494
|
+
(declare (function end-string-test))
|
495
|
+
(if (<= (the fixnum pos)
|
496
|
+
(the fixnum *end-string-pos*))
|
497
|
+
(return-from advance-fn pos))
|
498
|
+
(unless (setq *end-string-pos* (funcall end-string-test pos))
|
499
|
+
(return-from scan nil))
|
500
|
+
pos)))
|
501
|
+
(t
|
502
|
+
;; not enough optimization information about the regular
|
503
|
+
;; expression to optimize so we just return POS
|
504
|
+
(insert-advance-fn
|
505
|
+
(advance-fn (pos)
|
506
|
+
pos))))))
|
@@ -0,0 +1,172 @@
|
|
1
|
+
;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*-
|
2
|
+
;;; $Header: /usr/local/cvsrep/cl-ppcre/specials.lisp,v 1.43 2009/10/28 07:36:15 edi Exp $
|
3
|
+
|
4
|
+
;;; globally declared special variables
|
5
|
+
|
6
|
+
;;; Copyright (c) 2002-2009, Dr. Edmund Weitz. All rights reserved.
|
7
|
+
|
8
|
+
;;; Redistribution and use in source and binary forms, with or without
|
9
|
+
;;; modification, are permitted provided that the following conditions
|
10
|
+
;;; are met:
|
11
|
+
|
12
|
+
;;; * Redistributions of source code must retain the above copyright
|
13
|
+
;;; notice, this list of conditions and the following disclaimer.
|
14
|
+
|
15
|
+
;;; * Redistributions in binary form must reproduce the above
|
16
|
+
;;; copyright notice, this list of conditions and the following
|
17
|
+
;;; disclaimer in the documentation and/or other materials
|
18
|
+
;;; provided with the distribution.
|
19
|
+
|
20
|
+
;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
|
21
|
+
;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
22
|
+
;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23
|
+
;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
24
|
+
;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
25
|
+
;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
26
|
+
;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
27
|
+
;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
28
|
+
;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
29
|
+
;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
30
|
+
;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
|
32
|
+
(in-package :cl-ppcre)
|
33
|
+
|
34
|
+
;;; special variables used to effect declarations
|
35
|
+
|
36
|
+
(defvar *standard-optimize-settings*
|
37
|
+
'(optimize
|
38
|
+
speed
|
39
|
+
(safety 0)
|
40
|
+
(space 0)
|
41
|
+
(debug 1)
|
42
|
+
(compilation-speed 0)
|
43
|
+
#+:lispworks (hcl:fixnum-safety 0))
|
44
|
+
"The standard optimize settings used by most declaration expressions.")
|
45
|
+
|
46
|
+
(defvar *special-optimize-settings*
|
47
|
+
'(optimize speed space)
|
48
|
+
"Special optimize settings used only by a few declaration expressions.")
|
49
|
+
|
50
|
+
;;; special variables used by the lexer/parser combo
|
51
|
+
|
52
|
+
(defvar *extended-mode-p* nil
|
53
|
+
"Whether the parser will start in extended mode.")
|
54
|
+
(declaim (boolean *extended-mode-p*))
|
55
|
+
|
56
|
+
;;; special variables used by the SCAN function and the matchers
|
57
|
+
|
58
|
+
(defvar *regex-char-code-limit* char-code-limit
|
59
|
+
"The upper exclusive bound on the char-codes of characters which can
|
60
|
+
occur in character classes. Change this value BEFORE creating
|
61
|
+
scanners if you don't need the \(full) Unicode support of
|
62
|
+
implementations like AllegroCL, CLISP, LispWorks, or SBCL.")
|
63
|
+
(declaim (fixnum *regex-char-code-limit*))
|
64
|
+
|
65
|
+
(defvar *string* ""
|
66
|
+
"The string which is currently scanned by SCAN.
|
67
|
+
Will always be coerced to a SIMPLE-STRING.")
|
68
|
+
#+:lispworks
|
69
|
+
(declaim (lw:simple-text-string *string*))
|
70
|
+
#-:lispworks
|
71
|
+
(declaim (simple-string *string*))
|
72
|
+
|
73
|
+
(defvar *start-pos* 0
|
74
|
+
"Where to start scanning within *STRING*.")
|
75
|
+
(declaim (fixnum *start-pos*))
|
76
|
+
|
77
|
+
(defvar *real-start-pos* nil
|
78
|
+
"The real start of *STRING*. This is for repeated scans and is only used internally.")
|
79
|
+
(declaim (type (or null fixnum) *real-start-pos*))
|
80
|
+
|
81
|
+
(defvar *end-pos* 0
|
82
|
+
"Where to stop scanning within *STRING*.")
|
83
|
+
(declaim (fixnum *end-pos*))
|
84
|
+
|
85
|
+
(defvar *reg-starts* (make-array 0)
|
86
|
+
"An array which holds the start positions
|
87
|
+
of the current register candidates.")
|
88
|
+
(declaim (simple-vector *reg-starts*))
|
89
|
+
|
90
|
+
(defvar *regs-maybe-start* (make-array 0)
|
91
|
+
"An array which holds the next start positions
|
92
|
+
of the current register candidates.")
|
93
|
+
(declaim (simple-vector *regs-maybe-start*))
|
94
|
+
|
95
|
+
(defvar *reg-ends* (make-array 0)
|
96
|
+
"An array which holds the end positions
|
97
|
+
of the current register candidates.")
|
98
|
+
(declaim (simple-vector *reg-ends*))
|
99
|
+
|
100
|
+
(defvar *end-string-pos* nil
|
101
|
+
"Start of the next possible end-string candidate.")
|
102
|
+
|
103
|
+
(defvar *rep-num* 0
|
104
|
+
"Counts the number of \"complicated\" repetitions while the matchers
|
105
|
+
are built.")
|
106
|
+
(declaim (fixnum *rep-num*))
|
107
|
+
|
108
|
+
(defvar *zero-length-num* 0
|
109
|
+
"Counts the number of repetitions the inner regexes of which may
|
110
|
+
have zero-length while the matchers are built.")
|
111
|
+
(declaim (fixnum *zero-length-num*))
|
112
|
+
|
113
|
+
(defvar *repeat-counters* (make-array 0
|
114
|
+
:initial-element 0
|
115
|
+
:element-type 'fixnum)
|
116
|
+
"An array to keep track of how often
|
117
|
+
repetitive patterns have been tested already.")
|
118
|
+
(declaim (type (array fixnum (*)) *repeat-counters*))
|
119
|
+
|
120
|
+
(defvar *last-pos-stores* (make-array 0)
|
121
|
+
"An array to keep track of the last positions
|
122
|
+
where we saw repetitive patterns.
|
123
|
+
Only used for patterns which might have zero length.")
|
124
|
+
(declaim (simple-vector *last-pos-stores*))
|
125
|
+
|
126
|
+
(defvar *use-bmh-matchers* nil
|
127
|
+
"Whether the scanners created by CREATE-SCANNER should use the \(fast
|
128
|
+
but large) Boyer-Moore-Horspool matchers.")
|
129
|
+
|
130
|
+
(defvar *optimize-char-classes* nil
|
131
|
+
"Whether character classes should be compiled into look-ups into
|
132
|
+
O\(1) data structures. This is usually fast but will be costly in
|
133
|
+
terms of scanner creation time and might be costly in terms of size if
|
134
|
+
*REGEX-CHAR-CODE-LIMIT* is high. This value will be used as the :KIND
|
135
|
+
keyword argument to CREATE-OPTIMIZED-TEST-FUNCTION - see there for the
|
136
|
+
possible non-NIL values.")
|
137
|
+
|
138
|
+
(defvar *property-resolver* nil
|
139
|
+
"Should be NIL or a designator for a function which accepts strings
|
140
|
+
and returns unary character test functions or NIL. This 'resolver' is
|
141
|
+
intended to handle `character properties' like \\p{IsAlpha}. If
|
142
|
+
*PROPERTY-RESOLVER* is NIL, then the parser will simply treat \\p and
|
143
|
+
\\P as #\\p and #\\P as in older versions of CL-PPCRE.")
|
144
|
+
|
145
|
+
(defvar *allow-quoting* nil
|
146
|
+
"Whether the parser should support Perl's \\Q and \\E.")
|
147
|
+
|
148
|
+
(defvar *allow-named-registers* nil
|
149
|
+
"Whether the parser should support AllegroCL's named registers
|
150
|
+
\(?<name>\"<regex>\") and back-reference \\k<name> syntax.")
|
151
|
+
|
152
|
+
(pushnew :cl-ppcre *features*)
|
153
|
+
|
154
|
+
;; stuff for Nikodemus Siivola's HYPERDOC
|
155
|
+
;; see <http://common-lisp.net/project/hyperdoc/>
|
156
|
+
;; and <http://www.cliki.net/hyperdoc>
|
157
|
+
;; also used by LW-ADD-ONS
|
158
|
+
|
159
|
+
(defvar *hyperdoc-base-uri* "http://weitz.de/cl-ppcre/")
|
160
|
+
|
161
|
+
(let ((exported-symbols-alist
|
162
|
+
(loop for symbol being the external-symbols of :cl-ppcre
|
163
|
+
collect (cons symbol
|
164
|
+
(concatenate 'string
|
165
|
+
"#"
|
166
|
+
(string-downcase symbol))))))
|
167
|
+
(defun hyperdoc-lookup (symbol type)
|
168
|
+
(declare (ignore type))
|
169
|
+
(cdr (assoc symbol
|
170
|
+
exported-symbols-alist
|
171
|
+
:test #'eq))))
|
172
|
+
|